~bkerensa/ubuntu/raring/valgrind/merge-from-deb

« back to all changes in this revision

Viewing changes to VEX/priv/guest-amd64/toIR.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-11-16 17:56:30 UTC
  • mfrom: (1.2.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20061116175630-hatkgajb0twz0upw
Tags: upstream-3.2.1
Import upstream version 3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
4887
4887
               put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
4888
4888
               break;
4889
4889
 
4890
 
//..             case 0xF8: { /* FPREM -- not IEEE compliant */
4891
 
//..                IRTemp a1 = newTemp(Ity_F64);
4892
 
//..                IRTemp a2 = newTemp(Ity_F64);
4893
 
//..                DIP("fprem\n");
4894
 
//..                /* Do FPREM twice, once to get the remainder, and once
4895
 
//..                   to get the C3210 flag values. */
4896
 
//..                assign( a1, get_ST(0) );
4897
 
//..                assign( a2, get_ST(1) );
4898
 
//..                put_ST_UNCHECKED(0, binop(Iop_PRemF64,
4899
 
//..                                          mkexpr(a1), mkexpr(a2)));
4900
 
//..                put_C3210( binop(Iop_PRemC3210F64, mkexpr(a1), mkexpr(a2)) );
4901
 
//..                break;
4902
 
//..             }
4903
 
//.. 
 
4890
            case 0xF8: { /* FPREM -- not IEEE compliant */
 
4891
               IRTemp a1 = newTemp(Ity_F64);
 
4892
               IRTemp a2 = newTemp(Ity_F64);
 
4893
               DIP("fprem\n");
 
4894
               /* Do FPREM twice, once to get the remainder, and once
 
4895
                  to get the C3210 flag values. */
 
4896
               assign( a1, get_ST(0) );
 
4897
               assign( a2, get_ST(1) );
 
4898
               put_ST_UNCHECKED(0,
 
4899
                  triop(Iop_PRemF64,
 
4900
                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
 
4901
                        mkexpr(a1),
 
4902
                        mkexpr(a2)));
 
4903
               put_C3210(
 
4904
                  unop(Iop_32Uto64,
 
4905
                  triop(Iop_PRemC3210F64,
 
4906
                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
 
4907
                        mkexpr(a1),
 
4908
                        mkexpr(a2)) ));
 
4909
               break;
 
4910
            }
 
4911
 
4904
4912
            case 0xF9: /* FYL2XP1 */
4905
4913
               DIP("fyl2xp1\n");
4906
4914
               put_ST_UNCHECKED(1, 
5127
5135
                              loadLE(Ity_I32, mkexpr(addr))));
5128
5136
               break;
5129
5137
 
 
5138
            case 1: /* FISTTPL m32 (SSE3) */
 
5139
               DIP("fisttpl %s\n", dis_buf);
 
5140
               storeLE( mkexpr(addr), 
 
5141
                        binop(Iop_F64toI32, mkU32(Irrm_ZERO), get_ST(0)) );
 
5142
               fp_pop();
 
5143
               break;
 
5144
 
5130
5145
            case 2: /* FIST m32 */
5131
5146
               DIP("fistl %s\n", dis_buf);
5132
5147
               storeLE( mkexpr(addr), 
5444
5459
               put_ST(0, loadLE(Ity_F64, mkexpr(addr)));
5445
5460
               break;
5446
5461
 
 
5462
            case 1: /* FISTTPQ m64 (SSE3) */
 
5463
               DIP("fistppll %s\n", dis_buf);
 
5464
               storeLE( mkexpr(addr), 
 
5465
                        binop(Iop_F64toI64, mkU32(Irrm_ZERO), get_ST(0)) );
 
5466
               fp_pop();
 
5467
               break;
 
5468
 
5447
5469
            case 2: /* FST double-real */
5448
5470
               DIP("fstl %s\n", dis_buf);
5449
5471
               storeLE(mkexpr(addr), get_ST(0));
5776
5798
                                   loadLE(Ity_I16, mkexpr(addr)))));
5777
5799
               break;
5778
5800
 
 
5801
            case 1: /* FISTTPS m16 (SSE3) */
 
5802
               DIP("fisttps %s\n", dis_buf);
 
5803
               storeLE( mkexpr(addr), 
 
5804
                        unop(Iop_32to16,
 
5805
                             binop(Iop_F64toI32, mkU32(Irrm_ZERO), get_ST(0))) );
 
5806
               fp_pop();
 
5807
               break;
 
5808
 
5779
5809
//..             case 2: /* FIST m16 */
5780
5810
//..                DIP("fistp %s\n", dis_buf);
5781
5811
//..                storeLE( mkexpr(addr), 
7114
7144
//.. //-- 
7115
7145
 
7116
7146
static
7117
 
ULong dis_cmpxchg_G_E ( Prefix      pfx,
7118
 
                        Int         size, 
7119
 
                        Long        delta0 )
 
7147
ULong dis_cmpxchg_G_E ( /*OUT*/Bool* ok,
 
7148
                        Prefix       pfx,
 
7149
                        Int          size, 
 
7150
                        Long         delta0 )
7120
7151
{
7121
7152
   HChar dis_buf[50];
7122
7153
   Int   len;
7132
7163
   UChar  rm    = getUChar(delta0);
7133
7164
 
7134
7165
   if (epartIsReg(rm)) {
7135
 
      vassert(0); /* awaiting test case */
 
7166
      *ok = False;
 
7167
      return delta0;
 
7168
      /* awaiting test case */
7136
7169
      assign( dest, getIRegE(size, pfx, rm) );
7137
7170
      delta0++;
7138
7171
      DIP("cmpxchg%c %s,%s\n", nameISize(size),
7160
7193
      storeLE( mkexpr(addr), mkexpr(dest2) );
7161
7194
   }
7162
7195
 
7163
 
   return delta0;
7164
 
}
7165
 
 
 
7196
   *ok = True;
 
7197
   return delta0;
 
7198
}
 
7199
 
 
7200
static
 
7201
ULong dis_cmpxchg8b ( /*OUT*/Bool* ok,
 
7202
                      Prefix       pfx,
 
7203
                      Int          sz, 
 
7204
                      Long         delta0 )
 
7205
{
 
7206
   HChar dis_buf[50];
 
7207
   Int   len;
 
7208
 
 
7209
   IRType ty    = szToITy(sz);
 
7210
   IRTemp eq    = newTemp(Ity_I8);
 
7211
   IRTemp olda  = newTemp(ty);
 
7212
   IRTemp oldb  = newTemp(ty);
 
7213
   IRTemp oldc  = newTemp(ty);
 
7214
   IRTemp oldd  = newTemp(ty);
 
7215
   IRTemp newa  = newTemp(Ity_I64);
 
7216
   IRTemp newd  = newTemp(Ity_I64);
 
7217
   IRTemp oldml = newTemp(ty);
 
7218
   IRTemp oldmh = newTemp(ty);
 
7219
   IRTemp newml = newTemp(ty);
 
7220
   IRTemp newmh = newTemp(ty);
 
7221
   IRTemp addr  = IRTemp_INVALID;
 
7222
   IRTemp oldrf = newTemp(Ity_I64);
 
7223
   IRTemp newrf = newTemp(Ity_I64);
 
7224
   UChar  rm    = getUChar(delta0);
 
7225
   vassert(sz == 4 || sz == 8); /* guaranteed by caller */
 
7226
 
 
7227
   if (epartIsReg(rm)) {
 
7228
      *ok = False;
 
7229
      return delta0;
 
7230
   }
 
7231
 
 
7232
   addr = disAMode ( &len, pfx, delta0, dis_buf, 0 );
 
7233
   delta0 += len;
 
7234
   DIP("cmpxchg%s %s\n", sz == 4 ? "8" : "16", dis_buf);
 
7235
 
 
7236
   if (sz == 4) {
 
7237
      assign( olda,  getIReg32( R_RAX ) );
 
7238
      assign( oldb,  getIReg32( R_RBX ) );
 
7239
      assign( oldc,  getIReg32( R_RCX ) );
 
7240
      assign( oldd,  getIReg32( R_RDX ) );
 
7241
      assign( oldml, loadLE( Ity_I32, mkexpr(addr) ));
 
7242
      assign( oldmh, loadLE( Ity_I32, 
 
7243
                             binop(Iop_Add64,mkexpr(addr),mkU64(4)) ));
 
7244
      assign(eq, 
 
7245
         unop(Iop_1Uto8,
 
7246
              binop(Iop_CmpEQ32, 
 
7247
                    binop(Iop_Or32,
 
7248
                          binop(Iop_Xor32,mkexpr(olda),mkexpr(oldml)),
 
7249
                          binop(Iop_Xor32,mkexpr(oldd),mkexpr(oldmh))),
 
7250
                    mkU32(0))));
 
7251
      assign( newml, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(oldb)) );
 
7252
      assign( newmh, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldc)) );
 
7253
      assign( newa,  IRExpr_Mux0X(mkexpr(eq),
 
7254
                                  unop(Iop_32Uto64,mkexpr(oldml)),
 
7255
                                  getIRegRAX(8)) );
 
7256
      assign( newd,  IRExpr_Mux0X(mkexpr(eq),
 
7257
                                  unop(Iop_32Uto64,mkexpr(oldmh)),
 
7258
                                  getIRegRDX(8)) );
 
7259
 
 
7260
      storeLE( mkexpr(addr), mkexpr(newml) );
 
7261
      storeLE( binop(Iop_Add64,mkexpr(addr),mkU64(4)),
 
7262
               mkexpr(newmh) );
 
7263
      putIRegRAX( 8, mkexpr(newa) );
 
7264
      putIRegRDX( 8, mkexpr(newd) );
 
7265
   } else {
 
7266
      assign( olda, getIReg64( R_RAX ) );
 
7267
      assign( oldb, getIReg64( R_RBX ) );
 
7268
      assign( oldc, getIReg64( R_RCX ) );
 
7269
      assign( oldd, getIReg64( R_RDX ) );
 
7270
      assign( oldml, loadLE( Ity_I64, mkexpr(addr) ));
 
7271
      assign( oldmh, loadLE( Ity_I64, 
 
7272
                             binop(Iop_Add64,mkexpr(addr),mkU64(8)) ));
 
7273
      assign(eq, 
 
7274
         unop(Iop_1Uto8,
 
7275
              binop(Iop_CmpEQ64, 
 
7276
                    binop(Iop_Or64,
 
7277
                          binop(Iop_Xor64,mkexpr(olda),mkexpr(oldml)),
 
7278
                          binop(Iop_Xor64,mkexpr(oldd),mkexpr(oldmh))),
 
7279
                    mkU64(0))));
 
7280
      assign( newml, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(oldb)) );
 
7281
      assign( newmh, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldc)) );
 
7282
      assign( newa,  IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(olda)) );
 
7283
      assign( newd,  IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldd)) );
 
7284
 
 
7285
      storeLE( mkexpr(addr), mkexpr(newml) );
 
7286
      storeLE( binop(Iop_Add64,mkexpr(addr),mkU64(8)),
 
7287
               mkexpr(newmh) );
 
7288
      putIRegRAX( 8, mkexpr(newa) );
 
7289
      putIRegRDX( 8, mkexpr(newd) );
 
7290
   }
 
7291
 
 
7292
   /* And set the flags.  Z is set if original d:a == mem, else
 
7293
      cleared.  All others unchanged.  (This is different from normal
 
7294
      cmpxchg which just sets them according to SUB.). */
 
7295
   assign( oldrf, binop(Iop_And64, 
 
7296
                        mk_amd64g_calculate_rflags_all(),
 
7297
                        mkU64(~AMD64G_CC_MASK_Z)) );
 
7298
   assign( newrf,
 
7299
   binop(Iop_Or64,
 
7300
         mkexpr(oldrf),
 
7301
   binop(Iop_Shl64, 
 
7302
         binop(Iop_And64, unop(Iop_8Uto64, mkexpr(eq)), mkU64(1)),
 
7303
         mkU8(AMD64G_CC_SHIFT_Z))
 
7304
         ));
 
7305
      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
 
7306
      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
 
7307
      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(newrf) ));
 
7308
      /* Set NDEP even though it isn't used.  This makes redundant-PUT
 
7309
         elimination of previous stores to this field work better. */
 
7310
      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
 
7311
 
 
7312
   *ok = True;
 
7313
   return delta0;
 
7314
}
7166
7315
 
7167
7316
//.. //-- static
7168
7317
//.. //-- Addr dis_cmpxchg8b ( UCodeBlock* cb, 
9010
9159
   /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9011
9160
   /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put 
9012
9161
      zero-extend of it in ireg(G). */
9013
 
   if (haveNo66noF2noF3(pfx) && sz == 4
 
9162
   if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
9014
9163
       && insn[0] == 0x0F && insn[1] == 0xC5) {
9015
9164
      modrm = insn[2];
9016
9165
      if (epartIsReg(modrm)) {
9026
9175
            case 3:  assign(t5, mkexpr(t3)); break;
9027
9176
            default: vassert(0);
9028
9177
         }
9029
 
         putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_16Uto32, mkexpr(t5)));
 
9178
         if (sz == 8)
 
9179
            putIReg64(gregOfRexRM(pfx,modrm), unop(Iop_16Uto64, mkexpr(t5)));
 
9180
         else
 
9181
            putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_16Uto32, mkexpr(t5)));
9030
9182
         DIP("pextrw $%d,%s,%s\n",
9031
9183
             (Int)insn[3], nameMMXReg(eregLO3ofRM(modrm)),
9032
 
                           nameIReg32(gregOfRexRM(pfx,modrm)));
 
9184
                           sz==8 ? nameIReg64(gregOfRexRM(pfx,modrm))
 
9185
                                 : nameIReg32(gregOfRexRM(pfx,modrm))
 
9186
         );
9033
9187
         delta += 4;
9034
9188
         goto decode_success;
9035
9189
      } 
11111
11265
      goto decode_success;
11112
11266
   }
11113
11267
 
 
11268
   /* 66 0F F6 = PSADBW -- 2 x (8x8 -> 48 zeroes ++ u16) Sum Abs Diffs
 
11269
      from E(xmm or mem) to G(xmm) */
 
11270
   if (have66noF2noF3(pfx) && sz == 2 
 
11271
       && insn[0] == 0x0F && insn[1] == 0xF6) {
 
11272
      IRTemp s1V  = newTemp(Ity_V128);
 
11273
      IRTemp s2V  = newTemp(Ity_V128);
 
11274
      IRTemp dV   = newTemp(Ity_V128);
 
11275
      IRTemp s1Hi = newTemp(Ity_I64);
 
11276
      IRTemp s1Lo = newTemp(Ity_I64);
 
11277
      IRTemp s2Hi = newTemp(Ity_I64);
 
11278
      IRTemp s2Lo = newTemp(Ity_I64);
 
11279
      IRTemp dHi  = newTemp(Ity_I64);
 
11280
      IRTemp dLo  = newTemp(Ity_I64);
 
11281
      modrm = insn[2];
 
11282
      if (epartIsReg(modrm)) {
 
11283
         assign( s1V, getXMMReg(eregOfRexRM(pfx,modrm)) );
 
11284
         delta += 2+1;
 
11285
         DIP("psadbw %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
 
11286
                               nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11287
      } else {
 
11288
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
11289
         assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
 
11290
         delta += 2+alen;
 
11291
         DIP("psadbw %s,%s\n", dis_buf,
 
11292
                               nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11293
      }
 
11294
      assign( s2V, getXMMReg(gregOfRexRM(pfx,modrm)) );
 
11295
      assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
 
11296
      assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
 
11297
      assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
 
11298
      assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
 
11299
      assign( dHi, mkIRExprCCall(
 
11300
                      Ity_I64, 0/*regparms*/,
 
11301
                      "amd64g_calculate_mmx_psadbw", 
 
11302
                      &amd64g_calculate_mmx_psadbw,
 
11303
                      mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
 
11304
                   ));
 
11305
      assign( dLo, mkIRExprCCall(
 
11306
                      Ity_I64, 0/*regparms*/,
 
11307
                      "amd64g_calculate_mmx_psadbw", 
 
11308
                      &amd64g_calculate_mmx_psadbw,
 
11309
                      mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
 
11310
                   ));
 
11311
      assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
 
11312
      putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
 
11313
      goto decode_success;
 
11314
   }
 
11315
 
11114
11316
   /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
11115
11317
   if (have66noF2noF3(pfx) && sz == 2 
11116
11318
       && insn[0] == 0x0F && insn[1] == 0x70) {
11697
11899
      goto decode_success;
11698
11900
   }
11699
11901
 
11700
 
 
11701
11902
   /* ---------------------------------------------------- */
11702
11903
   /* --- end of the SSE/SSE2 decoder.                 --- */
11703
11904
   /* ---------------------------------------------------- */
11704
11905
 
 
11906
   /* ---------------------------------------------------- */
 
11907
   /* --- start of the SSE3 decoder.                   --- */
 
11908
   /* ---------------------------------------------------- */
 
11909
 
 
11910
   /* F3 0F 12 = MOVSLDUP -- move from E (mem or xmm) to G (xmm),
 
11911
      duplicating some lanes (2:2:0:0). */
 
11912
   /* F3 0F 16 = MOVSHDUP -- move from E (mem or xmm) to G (xmm),
 
11913
      duplicating some lanes (3:3:1:1). */
 
11914
   if (haveF3no66noF2(pfx) && sz == 4
 
11915
       && insn[0] == 0x0F && (insn[1] == 0x12 || insn[1] == 0x16)) {
 
11916
      IRTemp s3, s2, s1, s0;
 
11917
      IRTemp sV  = newTemp(Ity_V128);
 
11918
      Bool   isH = insn[1] == 0x16;
 
11919
      s3 = s2 = s1 = s0 = IRTemp_INVALID;
 
11920
 
 
11921
      modrm = insn[2];
 
11922
      if (epartIsReg(modrm)) {
 
11923
         assign( sV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
11924
         DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
 
11925
                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
 
11926
                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11927
         delta += 2+1;
 
11928
      } else {
 
11929
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
11930
         assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
 
11931
         DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
 
11932
             dis_buf,
 
11933
             nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11934
         delta += 2+alen;
 
11935
      }
 
11936
 
 
11937
      breakup128to32s( sV, &s3, &s2, &s1, &s0 );
 
11938
      putXMMReg( gregOfRexRM(pfx,modrm), 
 
11939
                 isH ? mk128from32s( s3, s3, s1, s1 )
 
11940
                     : mk128from32s( s2, s2, s0, s0 ) );
 
11941
      goto decode_success;
 
11942
   }
 
11943
 
 
11944
   /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm),
 
11945
      duplicating some lanes (0:1:0:1). */
 
11946
   if (haveF2no66noF3(pfx) && sz == 4 
 
11947
       && insn[0] == 0x0F && insn[1] == 0x12) {
 
11948
      IRTemp sV = newTemp(Ity_V128);
 
11949
      IRTemp d0 = newTemp(Ity_I64);
 
11950
 
 
11951
      modrm = insn[2];
 
11952
      if (epartIsReg(modrm)) {
 
11953
         assign( sV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
11954
         DIP("movddup %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
 
11955
                                nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11956
         delta += 2+1;
 
11957
         assign ( d0, unop(Iop_V128to64, mkexpr(sV)) );
 
11958
      } else {
 
11959
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
11960
         assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
 
11961
         DIP("movddup %s,%s\n", dis_buf,
 
11962
                                nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11963
         delta += 2+alen;
 
11964
      }
 
11965
 
 
11966
      putXMMReg( gregOfRexRM(pfx,modrm), 
 
11967
                 binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) );
 
11968
      goto decode_success;
 
11969
   }
 
11970
 
 
11971
   /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */
 
11972
   if (haveF2no66noF3(pfx) && sz == 4 
 
11973
       && insn[0] == 0x0F && insn[1] == 0xD0) {
 
11974
      IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
 
11975
      IRTemp eV   = newTemp(Ity_V128);
 
11976
      IRTemp gV   = newTemp(Ity_V128);
 
11977
      IRTemp addV = newTemp(Ity_V128);
 
11978
      IRTemp subV = newTemp(Ity_V128);
 
11979
      a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
 
11980
 
 
11981
      modrm = insn[2];
 
11982
      if (epartIsReg(modrm)) {
 
11983
         assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
11984
         DIP("addsubps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
 
11985
                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11986
         delta += 2+1;
 
11987
      } else {
 
11988
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
11989
         assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
 
11990
         DIP("addsubps %s,%s\n", dis_buf,
 
11991
                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
 
11992
         delta += 2+alen;
 
11993
      }
 
11994
 
 
11995
      assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
 
11996
 
 
11997
      assign( addV, binop(Iop_Add32Fx4, mkexpr(gV), mkexpr(eV)) );
 
11998
      assign( subV, binop(Iop_Sub32Fx4, mkexpr(gV), mkexpr(eV)) );
 
11999
 
 
12000
      breakup128to32s( addV, &a3, &a2, &a1, &a0 );
 
12001
      breakup128to32s( subV, &s3, &s2, &s1, &s0 );
 
12002
 
 
12003
      putXMMReg( gregOfRexRM(pfx,modrm), mk128from32s( a3, s2, a1, s0 ));
 
12004
      goto decode_success;
 
12005
   }
 
12006
 
 
12007
   /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */
 
12008
   if (have66noF2noF3(pfx) && sz == 2 
 
12009
       && insn[0] == 0x0F && insn[1] == 0xD0) {
 
12010
      IRTemp eV   = newTemp(Ity_V128);
 
12011
      IRTemp gV   = newTemp(Ity_V128);
 
12012
      IRTemp addV = newTemp(Ity_V128);
 
12013
      IRTemp subV = newTemp(Ity_V128);
 
12014
      IRTemp a1     = newTemp(Ity_I64);
 
12015
      IRTemp s0     = newTemp(Ity_I64);
 
12016
 
 
12017
      modrm = insn[2];
 
12018
      if (epartIsReg(modrm)) {
 
12019
         assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
12020
         DIP("addsubpd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
 
12021
                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12022
         delta += 2+1;
 
12023
      } else {
 
12024
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
12025
         assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
 
12026
         DIP("addsubpd %s,%s\n", dis_buf,
 
12027
                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12028
         delta += 2+alen;
 
12029
      }
 
12030
 
 
12031
      assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
 
12032
 
 
12033
      assign( addV, binop(Iop_Add64Fx2, mkexpr(gV), mkexpr(eV)) );
 
12034
      assign( subV, binop(Iop_Sub64Fx2, mkexpr(gV), mkexpr(eV)) );
 
12035
 
 
12036
      assign( a1, unop(Iop_V128HIto64, mkexpr(addV) ));
 
12037
      assign( s0, unop(Iop_V128to64,   mkexpr(subV) ));
 
12038
 
 
12039
      putXMMReg( gregOfRexRM(pfx,modrm), 
 
12040
                 binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) );
 
12041
      goto decode_success;
 
12042
   }
 
12043
 
 
12044
   /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */
 
12045
   /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */
 
12046
   if (haveF2no66noF3(pfx) && sz == 4 
 
12047
       && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
 
12048
      IRTemp e3, e2, e1, e0, g3, g2, g1, g0;
 
12049
      IRTemp eV     = newTemp(Ity_V128);
 
12050
      IRTemp gV     = newTemp(Ity_V128);
 
12051
      IRTemp leftV  = newTemp(Ity_V128);
 
12052
      IRTemp rightV = newTemp(Ity_V128);
 
12053
      Bool   isAdd  = insn[1] == 0x7C;
 
12054
      HChar* str    = isAdd ? "add" : "sub";
 
12055
      e3 = e2 = e1 = e0 = g3 = g2 = g1 = g0 = IRTemp_INVALID;
 
12056
 
 
12057
      modrm = insn[2];
 
12058
      if (epartIsReg(modrm)) {
 
12059
         assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
12060
         DIP("h%sps %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
 
12061
                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12062
         delta += 2+1;
 
12063
      } else {
 
12064
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
12065
         assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
 
12066
         DIP("h%sps %s,%s\n", str, dis_buf,
 
12067
                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12068
         delta += 2+alen;
 
12069
      }
 
12070
 
 
12071
      assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
 
12072
 
 
12073
      breakup128to32s( eV, &e3, &e2, &e1, &e0 );
 
12074
      breakup128to32s( gV, &g3, &g2, &g1, &g0 );
 
12075
 
 
12076
      assign( leftV,  mk128from32s( e2, e0, g2, g0 ) );
 
12077
      assign( rightV, mk128from32s( e3, e1, g3, g1 ) );
 
12078
 
 
12079
      putXMMReg( gregOfRexRM(pfx,modrm), 
 
12080
                 binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4, 
 
12081
                       mkexpr(leftV), mkexpr(rightV) ) );
 
12082
      goto decode_success;
 
12083
   }
 
12084
 
 
12085
   /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */
 
12086
   /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */
 
12087
   if (have66noF2noF3(pfx) && sz == 2 
 
12088
       && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
 
12089
      IRTemp e1     = newTemp(Ity_I64);
 
12090
      IRTemp e0     = newTemp(Ity_I64);
 
12091
      IRTemp g1     = newTemp(Ity_I64);
 
12092
      IRTemp g0     = newTemp(Ity_I64);
 
12093
      IRTemp eV     = newTemp(Ity_V128);
 
12094
      IRTemp gV     = newTemp(Ity_V128);
 
12095
      IRTemp leftV  = newTemp(Ity_V128);
 
12096
      IRTemp rightV = newTemp(Ity_V128);
 
12097
      Bool   isAdd  = insn[1] == 0x7C;
 
12098
      HChar* str    = isAdd ? "add" : "sub";
 
12099
 
 
12100
      modrm = insn[2];
 
12101
      if (epartIsReg(modrm)) {
 
12102
         assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
 
12103
         DIP("h%spd %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
 
12104
                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12105
         delta += 2+1;
 
12106
      } else {
 
12107
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
12108
         assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
 
12109
         DIP("h%spd %s,%s\n", str, dis_buf,
 
12110
                              nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12111
         delta += 2+alen;
 
12112
      }
 
12113
 
 
12114
      assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
 
12115
 
 
12116
      assign( e1, unop(Iop_V128HIto64, mkexpr(eV) ));
 
12117
      assign( e0, unop(Iop_V128to64, mkexpr(eV) ));
 
12118
      assign( g1, unop(Iop_V128HIto64, mkexpr(gV) ));
 
12119
      assign( g0, unop(Iop_V128to64, mkexpr(gV) ));
 
12120
 
 
12121
      assign( leftV,  binop(Iop_64HLtoV128, mkexpr(e0),mkexpr(g0)) );
 
12122
      assign( rightV, binop(Iop_64HLtoV128, mkexpr(e1),mkexpr(g1)) );
 
12123
 
 
12124
      putXMMReg( gregOfRexRM(pfx,modrm), 
 
12125
                 binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2, 
 
12126
                       mkexpr(leftV), mkexpr(rightV) ) );
 
12127
      goto decode_success;
 
12128
   }
 
12129
 
 
12130
   /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */
 
12131
   if (haveF2no66noF3(pfx) && sz == 4 
 
12132
       && insn[0] == 0x0F && insn[1] == 0xF0) {
 
12133
      modrm = insn[2];
 
12134
      if (epartIsReg(modrm)) {
 
12135
         goto decode_failure;
 
12136
      } else {
 
12137
         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
 
12138
         putXMMReg( gregOfRexRM(pfx,modrm), 
 
12139
                    loadLE(Ity_V128, mkexpr(addr)) );
 
12140
         DIP("lddqu %s,%s\n", dis_buf,
 
12141
                              nameXMMReg(gregOfRexRM(pfx,modrm)));
 
12142
         delta += 2+alen;
 
12143
      }
 
12144
      goto decode_success;
 
12145
   }
 
12146
 
 
12147
   /* ---------------------------------------------------- */
 
12148
   /* --- end of the SSE3 decoder.                     --- */
 
12149
   /* ---------------------------------------------------- */
 
12150
 
11705
12151
   /*after_sse_decoders:*/
11706
12152
 
11707
12153
   /* Get the primary opcode. */
12701
13147
      t2 = newTemp(ty);
12702
13148
      assign( t1, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
12703
13149
      putIReg64(R_RSP, mkexpr(t1) );
 
13150
      /* stop mkU16 asserting if d32 is a negative 16-bit number
 
13151
         (bug #132813) */
 
13152
      if (ty == Ity_I16)
 
13153
         d64 &= 0xFFFF;
12704
13154
      storeLE( mkexpr(t1), mkU(ty,d64) );
12705
13155
      DIP("push%c $%lld\n", nameISize(sz), (Long)d64);
12706
13156
      break;
12708
13158
   case 0x9C: /* PUSHF */ {
12709
13159
      /* Note.  There is no encoding for a 32-bit pushf in 64-bit
12710
13160
         mode.  So sz==4 actually means sz==8. */
 
13161
      /* 24 July 06: has also been seen with a redundant REX prefix,
 
13162
         so must also allow sz==8. */
12711
13163
      if (haveF2orF3(pfx)) goto decode_failure;
12712
 
      vassert(sz == 2 || sz == 4);
 
13164
      vassert(sz == 2 || sz == 4 || sz == 8);
12713
13165
      if (sz == 4) sz = 8;
12714
13166
      if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
12715
13167
 
13315
13767
               binop(Iop_Or32,
13316
13768
                  binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
13317
13769
               binop(Iop_Or32,
13318
 
                  binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)), 
 
13770
                  binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)),
13319
13771
                                   mkU32(0x00FF0000)),
13320
13772
               binop(Iop_Or32,
13321
13773
                  binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
13329
13781
            break;
13330
13782
         }
13331
13783
         else if (sz == 8) {
 
13784
            IRTemp m8  = newTemp(Ity_I64);
 
13785
            IRTemp s8  = newTemp(Ity_I64);
 
13786
            IRTemp m16 = newTemp(Ity_I64);
 
13787
            IRTemp s16 = newTemp(Ity_I64);
 
13788
            IRTemp m32 = newTemp(Ity_I64);
13332
13789
            t1 = newTemp(Ity_I64);
13333
13790
            t2 = newTemp(Ity_I64);
13334
13791
            assign( t1, getIRegRexB(8, pfx, opc-0xC8) );
13335
13792
 
13336
 
#           define LANE(_nn)                                          \
13337
 
               binop( Iop_Shl64,                                      \
13338
 
                      binop( Iop_And64,                               \
13339
 
                             binop(Iop_Shr64, mkexpr(t1),             \
13340
 
                                              mkU8(8 * (7 - (_nn)))), \
13341
 
                             mkU64(0xFF)),                            \
13342
 
                      mkU8(8 * (_nn)))
13343
 
 
13344
 
            assign( 
13345
 
               t2,
13346
 
               binop(Iop_Or64,
13347
 
                     binop(Iop_Or64,
13348
 
                           binop(Iop_Or64,LANE(0),LANE(1)),
13349
 
                           binop(Iop_Or64,LANE(2),LANE(3))
13350
 
                     ),
13351
 
                     binop(Iop_Or64,
13352
 
                           binop(Iop_Or64,LANE(4),LANE(5)),
13353
 
                           binop(Iop_Or64,LANE(6),LANE(7))
13354
 
                     )
13355
 
               )
13356
 
            );
13357
 
 
13358
 
#           undef LANE
 
13793
            assign( m8, mkU64(0xFF00FF00FF00FF00ULL) );
 
13794
            assign( s8,
 
13795
                    binop(Iop_Or64,
 
13796
                          binop(Iop_Shr64,
 
13797
                                binop(Iop_And64,mkexpr(t1),mkexpr(m8)),
 
13798
                                mkU8(8)),
 
13799
                          binop(Iop_And64,
 
13800
                                binop(Iop_Shl64,mkexpr(t1),mkU8(8)),
 
13801
                                mkexpr(m8))
 
13802
                         ) 
 
13803
                  );
 
13804
 
 
13805
            assign( m16, mkU64(0xFFFF0000FFFF0000ULL) );
 
13806
            assign( s16,
 
13807
                    binop(Iop_Or64,
 
13808
                          binop(Iop_Shr64,
 
13809
                                binop(Iop_And64,mkexpr(s8),mkexpr(m16)),
 
13810
                                mkU8(16)),
 
13811
                          binop(Iop_And64,
 
13812
                                binop(Iop_Shl64,mkexpr(s8),mkU8(16)),
 
13813
                                mkexpr(m16))
 
13814
                         ) 
 
13815
                  );
 
13816
 
 
13817
            assign( m32, mkU64(0xFFFFFFFF00000000ULL) );
 
13818
            assign( t2,
 
13819
                    binop(Iop_Or64,
 
13820
                          binop(Iop_Shr64,
 
13821
                                binop(Iop_And64,mkexpr(s16),mkexpr(m32)),
 
13822
                                mkU8(32)),
 
13823
                          binop(Iop_And64,
 
13824
                                binop(Iop_Shl64,mkexpr(s16),mkU8(32)),
 
13825
                                mkexpr(m32))
 
13826
                         ) 
 
13827
                  );
13359
13828
 
13360
13829
            putIRegRexB(8, pfx, opc-0xC8, mkexpr(t2));
13361
13830
            DIP("bswapq %s\n", nameIRegRexB(8, pfx, opc-0xC8));
13417
13886
//..       case 0xB0: /* CMPXCHG Gb,Eb */
13418
13887
//..          delta = dis_cmpxchg_G_E ( sorb, 1, delta );
13419
13888
//..          break;
13420
 
      case 0xB1: /* CMPXCHG Gv,Ev */
 
13889
      case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
 
13890
         Bool ok = True;
13421
13891
         if (haveF2orF3(pfx)) goto decode_failure;
13422
 
         delta = dis_cmpxchg_G_E ( pfx, sz, delta );
13423
 
         break;
13424
 
//.. //--       case 0xC7: /* CMPXCHG8B Gv */
13425
 
//.. //--          eip = dis_cmpxchg8b ( cb, sorb, eip );
13426
 
//.. //--          break;
13427
 
//.. //-- 
 
13892
         if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
 
13893
         delta = dis_cmpxchg_G_E ( &ok, pfx, sz, delta );
 
13894
         if (!ok) goto decode_failure;
 
13895
         break;
 
13896
      }
 
13897
      case 0xC7: { /* CMPXCHG8B Ev, CMPXCHG16B Ev */
 
13898
         Bool ok = True;
 
13899
         if (have66orF2orF3(pfx)) goto decode_failure;
 
13900
         if (sz != 4 && sz != 8) goto decode_failure;
 
13901
         delta = dis_cmpxchg8b ( &ok, pfx, sz, delta );
 
13902
         break;
 
13903
      }
 
13904
 
13428
13905
      /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
13429
13906
 
13430
13907
      case 0xA2: { /* CPUID */
13520
13997
         delta = dis_mul_E_G ( pfx, sz, delta );
13521
13998
         break;
13522
13999
 
 
14000
      /* =-=-=-=-=-=-=-=-=- NOPs =-=-=-=-=-=-=-=-=-=-=-= */
 
14001
 
 
14002
      case 0x1F:
 
14003
         if (haveF2orF3(pfx)) goto decode_failure;
 
14004
         modrm = getUChar(delta);
 
14005
         if (epartIsReg(modrm)) goto decode_failure;
 
14006
         addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
 
14007
         delta += alen;
 
14008
         DIP("nop%c %s\n", nameISize(sz), dis_buf);
 
14009
         break;
 
14010
 
13523
14011
      /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
13524
14012
      case 0x80:
13525
14013
      case 0x81: