#define OFFB_CC_DEP2 offsetof(VexGuestAMD64State,guest_CC_DEP2)
#define OFFB_CC_NDEP offsetof(VexGuestAMD64State,guest_CC_NDEP)
-//.. #define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0])
-//.. #define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0])
+#define OFFB_FPREGS offsetof(VexGuestAMD64State,guest_FPREG[0])
+#define OFFB_FPTAGS offsetof(VexGuestAMD64State,guest_FPTAG[0])
#define OFFB_DFLAG offsetof(VexGuestAMD64State,guest_DFLAG)
#define OFFB_IDFLAG offsetof(VexGuestAMD64State,guest_IDFLAG)
-//.. #define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP)
+#define OFFB_FTOP offsetof(VexGuestAMD64State,guest_FTOP)
//.. #define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210)
//.. #define OFFB_FPROUND offsetof(VexGuestX86State,guest_FPROUND)
//..
static Bool have66noF2noF3 ( Prefix pfx )
{
return
- toBool(((pfx & PFX_66) | ((~pfx) & (PFX_F2|PFX_F3))) > 0);
+ toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_66);
}
/* Return True iff pfx has F2 set and 66 and F3 clear */
static Bool haveF2no66noF3 ( Prefix pfx )
{
return
- toBool(((pfx & PFX_F2) | ((~pfx) & (PFX_66|PFX_F3))) > 0);
+ toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F2);
+}
+
+/* Return True iff pfx has F3 set and 66 and F2 clear */
+static Bool haveF3no66noF2 ( Prefix pfx )
+{
+ return
+ toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F3);
}
/* Return True iff pfx has 66, F2 and F3 clear */
static Bool haveNo66noF2noF3 ( Prefix pfx )
{
return
- toBool((((~pfx) & (PFX_66|PFX_F2|PFX_F3))) > 0);
+ toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);
}
/* Clear all the segment-override bits in a prefix. */
//.. vassert(laneno >= 0 && laneno < 8);
//.. return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
//.. }
-//..
-//.. static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
-//.. {
-//.. /* Correct for little-endian host only. */
-//.. vassert(!host_is_bigendian);
-//.. vassert(laneno >= 0 && laneno < 4);
-//.. return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
-//.. }
+
+static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
+{
+ /* Correct for little-endian host only. */
+ vassert(!host_is_bigendian);
+ vassert(laneno >= 0 && laneno < 4);
+ return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
+}
static Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
{
return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
}
-//.. static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
-//.. {
-//.. return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
-//.. }
-//..
+static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
+{
+ return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
+}
+
//.. static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
//.. {
//.. return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
}
-//.. static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
-//.. {
-//.. vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F32);
-//.. stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
-//.. }
-//..
-//.. static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
-//.. {
-//.. vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
-//.. stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
-//.. }
-//..
+static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F32);
+ stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+}
+
+static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
+ stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+}
+
//.. static void putXMMRegLane16 ( UInt xmmreg, Int laneno, IRExpr* e )
//.. {
//.. vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I16);
//.. {
//.. stmt( IRStmt_Put( OFFB_EMWARN, e ) );
//.. }
-//..
-//.. /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
-//..
-//.. static IRExpr* mkQNaN64 ( void )
-//.. {
-//.. /* QNaN is 0 2047 1 0(51times)
-//.. == 0b 11111111111b 1 0(51times)
-//.. == 0x7FF8 0000 0000 0000
-//.. */
-//.. return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
-//.. }
-//..
-//.. /* --------- Get/put the top-of-stack pointer. --------- */
-//..
-//.. static IRExpr* get_ftop ( void )
-//.. {
-//.. return IRExpr_Get( OFFB_FTOP, Ity_I32 );
-//.. }
-//..
-//.. static void put_ftop ( IRExpr* e )
-//.. {
-//.. stmt( IRStmt_Put( OFFB_FTOP, e ) );
-//.. }
-//..
+
+/* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
+
+static IRExpr* mkQNaN64 ( void )
+{
+ /* QNaN is 0 2047 1 0(51times)
+ == 0b 11111111111b 1 0(51times)
+ == 0x7FF8 0000 0000 0000
+ */
+ return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
+}
+
+/* --------- Get/put the top-of-stack pointer :: Ity_I32 --------- */
+
+static IRExpr* get_ftop ( void )
+{
+ return IRExpr_Get( OFFB_FTOP, Ity_I32 );
+}
+
+static void put_ftop ( IRExpr* e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I32);
+ stmt( IRStmt_Put( OFFB_FTOP, e ) );
+}
+
//.. /* --------- Get/put the C3210 bits. --------- */
//..
//.. static IRExpr* get_C3210 ( void )
//.. {
//.. return binop( Iop_And32, get_fpround(), mkU32(3) );
//.. }
-//..
-//..
-//.. /* --------- Get/set FP register tag bytes. --------- */
-//..
-//.. /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
-//..
-//.. static void put_ST_TAG ( Int i, IRExpr* value )
-//.. {
-//.. IRArray* descr;
-//.. vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
-//.. descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//.. stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
-//.. }
-//..
-//.. /* Given i, generate an expression yielding 'ST_TAG(i)'. This will be
-//.. zero to indicate "Empty" and nonzero to indicate "NonEmpty". */
-//..
-//.. static IRExpr* get_ST_TAG ( Int i )
-//.. {
-//.. IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//.. return IRExpr_GetI( descr, get_ftop(), i );
-//.. }
-//..
-//..
-//.. /* --------- Get/set FP registers. --------- */
-//..
-//.. /* Given i, and some expression e, emit 'ST(i) = e' and set the
-//.. register's tag to indicate the register is full. The previous
-//.. state of the register is not checked. */
-//..
-//.. static void put_ST_UNCHECKED ( Int i, IRExpr* value )
-//.. {
-//.. IRArray* descr;
-//.. vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
-//.. descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
-//.. stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
-//.. /* Mark the register as in-use. */
-//.. put_ST_TAG(i, mkU8(1));
-//.. }
-//..
-//.. /* Given i, and some expression e, emit
-//.. ST(i) = is_full(i) ? NaN : e
-//.. and set the tag accordingly.
-//.. */
-//..
-//.. static void put_ST ( Int i, IRExpr* value )
-//.. {
-//.. put_ST_UNCHECKED( i,
-//.. IRExpr_Mux0X( get_ST_TAG(i),
-//.. /* 0 means empty */
-//.. value,
-//.. /* non-0 means full */
-//.. mkQNaN64()
-//.. )
-//.. );
-//.. }
-//..
-//..
-//.. /* Given i, generate an expression yielding 'ST(i)'. */
-//..
-//.. static IRExpr* get_ST_UNCHECKED ( Int i )
-//.. {
-//.. IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
-//.. return IRExpr_GetI( descr, get_ftop(), i );
-//.. }
-//..
-//..
-//.. /* Given i, generate an expression yielding
-//.. is_full(i) ? ST(i) : NaN
-//.. */
-//..
-//.. static IRExpr* get_ST ( Int i )
-//.. {
-//.. return
-//.. IRExpr_Mux0X( get_ST_TAG(i),
-//.. /* 0 means empty */
-//.. mkQNaN64(),
-//.. /* non-0 means full */
-//.. get_ST_UNCHECKED(i));
-//.. }
-//..
-//..
-//.. /* Adjust FTOP downwards by one register. */
-//..
-//.. static void fp_push ( void )
-//.. {
-//.. put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
-//.. }
-//..
-//.. /* Adjust FTOP upwards by one register, and mark the vacated register
-//.. as empty. */
-//..
-//.. static void fp_pop ( void )
-//.. {
-//.. put_ST_TAG(0, mkU8(0));
-//.. put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
-//.. }
-//..
+
+
+/* --------- Get/set FP register tag bytes. --------- */
+
+/* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
+
+static void put_ST_TAG ( Int i, IRExpr* value )
+{
+ IRArray* descr;
+ vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
+ descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+ stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+}
+
+/* Given i, generate an expression yielding 'ST_TAG(i)'. This will be
+ zero to indicate "Empty" and nonzero to indicate "NonEmpty". */
+
+static IRExpr* get_ST_TAG ( Int i )
+{
+ IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+ return IRExpr_GetI( descr, get_ftop(), i );
+}
+
+
+/* --------- Get/set FP registers. --------- */
+
+/* Given i, and some expression e, emit 'ST(i) = e' and set the
+ register's tag to indicate the register is full. The previous
+ state of the register is not checked. */
+
+static void put_ST_UNCHECKED ( Int i, IRExpr* value )
+{
+ IRArray* descr;
+ vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
+ descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+ stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+ /* Mark the register as in-use. */
+ put_ST_TAG(i, mkU8(1));
+}
+
+/* Given i, and some expression e, emit
+ ST(i) = is_full(i) ? NaN : e
+ and set the tag accordingly.
+*/
+
+static void put_ST ( Int i, IRExpr* value )
+{
+ put_ST_UNCHECKED( i,
+ IRExpr_Mux0X( get_ST_TAG(i),
+ /* 0 means empty */
+ value,
+ /* non-0 means full */
+ mkQNaN64()
+ )
+ );
+}
+
+
+/* Given i, generate an expression yielding 'ST(i)'. */
+
+static IRExpr* get_ST_UNCHECKED ( Int i )
+{
+ IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+ return IRExpr_GetI( descr, get_ftop(), i );
+}
+
+
+/* Given i, generate an expression yielding
+ is_full(i) ? ST(i) : NaN
+*/
+
+static IRExpr* get_ST ( Int i )
+{
+ return
+ IRExpr_Mux0X( get_ST_TAG(i),
+ /* 0 means empty */
+ mkQNaN64(),
+ /* non-0 means full */
+ get_ST_UNCHECKED(i));
+}
+
+
+/* Adjust FTOP downwards by one register. */
+
+static void fp_push ( void )
+{
+ put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
+}
+
+/* Adjust FTOP upwards by one register, and mark the vacated register
+ as empty. */
+
+static void fp_pop ( void )
+{
+ put_ST_TAG(0, mkU8(0));
+ put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
+}
+
//.. /* Clear the C2 bit of the FPU status register, for
//.. sin/cos/tan/sincos. */
//..
//.. if (pop_after)
//.. fp_pop();
//.. }
-//..
-//..
-//.. static
-//.. UInt dis_FPU ( Bool* decode_ok, UChar sorb, ULong delta )
-//.. {
-//.. Int len;
-//.. UInt r_src, r_dst;
-//.. HChar dis_buf[50];
-//.. IRTemp t1, t2;
-//..
-//.. /* On entry, delta points at the second byte of the insn (the modrm
-//.. byte).*/
-//.. UChar first_opcode = getUChar(delta-1);
-//.. UChar modrm = getUChar(delta+0);
-//..
+
+
+static
+ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
+{
+ Int len;
+ UInt r_src, r_dst;
+ HChar dis_buf[50];
+ IRTemp t1, t2;
+
+ /* On entry, delta points at the second byte of the insn (the modrm
+ byte).*/
+ UChar first_opcode = getUChar(delta-1);
+ UChar modrm = getUChar(delta+0);
+
//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
//..
//.. if (first_opcode == 0xD8) {
//.. }
//.. }
//.. }
-//..
-//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
+
+ /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
//.. else
-//.. if (first_opcode == 0xD9) {
-//.. if (modrm < 0xC0) {
-//..
-//.. /* bits 5,4,3 are an opcode extension, and the modRM also
-//.. specifies an address. */
-//.. IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//.. delta += len;
-//..
-//.. switch (gregOfRM(modrm)) {
-//..
+ if (first_opcode == 0xD9) {
+ if (modrm < 0xC0) {
+
+ /* bits 5,4,3 are an opcode extension, and the modRM also
+ specifies an address. */
+ IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+ delta += len;
+
+ switch (gregOfRM(modrm)) {
+
//.. case 0: /* FLD single-real */
//.. DIP("flds %s\n", dis_buf);
//.. fp_push();
//.. )
//.. );
//.. break;
-//..
-//.. default:
-//.. vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//.. vex_printf("first_opcode == 0xD9\n");
-//.. goto decode_fail;
-//.. }
-//..
-//.. } else {
-//.. delta++;
-//.. switch (modrm) {
-//..
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xD9\n");
+ goto decode_fail;
+ }
+
+ } else {
+ delta++;
+ switch (modrm) {
+
//.. case 0xC0 ... 0xC7: /* FLD %st(?) */
//.. r_src = (UInt)modrm - 0xC0;
//.. DIP("fld %%st(%d)\n", r_src);
//.. fp_push();
//.. put_ST(0, mkexpr(t1));
//.. break;
-//..
-//.. case 0xC8 ... 0xCF: /* FXCH %st(?) */
-//.. r_src = (UInt)modrm - 0xC8;
-//.. DIP("fxch %%st(%d)\n", r_src);
-//.. t1 = newTemp(Ity_F64);
-//.. t2 = newTemp(Ity_F64);
-//.. assign(t1, get_ST(0));
-//.. assign(t2, get_ST(r_src));
-//.. put_ST_UNCHECKED(0, mkexpr(t2));
-//.. put_ST_UNCHECKED(r_src, mkexpr(t1));
-//.. break;
-//..
-//.. case 0xE0: /* FCHS */
-//.. DIP("fchs\n");
-//.. put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
-//.. break;
-//..
+
+ case 0xC8 ... 0xCF: /* FXCH %st(?) */
+ r_src = (UInt)modrm - 0xC8;
+ DIP("fxch %%st(%d)\n", r_src);
+ t1 = newTemp(Ity_F64);
+ t2 = newTemp(Ity_F64);
+ assign(t1, get_ST(0));
+ assign(t2, get_ST(r_src));
+ put_ST_UNCHECKED(0, mkexpr(t2));
+ put_ST_UNCHECKED(r_src, mkexpr(t1));
+ break;
+
+ case 0xE0: /* FCHS */
+ DIP("fchs\n");
+ put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
+ break;
+
//.. case 0xE1: /* FABS */
//.. DIP("fabs\n");
//.. put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
//.. put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
//.. clear_C2(); /* HACK */
//.. break;
-//..
-//.. default:
-//.. goto decode_fail;
-//.. }
-//.. }
-//.. }
-//..
-//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
-//.. else
-//.. if (first_opcode == 0xDA) {
-//..
-//.. if (modrm < 0xC0) {
-//..
-//.. /* bits 5,4,3 are an opcode extension, and the modRM also
-//.. specifies an address. */
-//.. IROp fop;
-//.. IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//.. delta += len;
-//.. switch (gregOfRM(modrm)) {
-//..
+
+ default:
+ goto decode_fail;
+ }
+ }
+ }
+
+ /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
+ else
+ if (first_opcode == 0xDA) {
+
+ if (modrm < 0xC0) {
+
+ /* bits 5,4,3 are an opcode extension, and the modRM also
+ specifies an address. */
+ IROp fop;
+ IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+ delta += len;
+ switch (gregOfRM(modrm)) {
+
//.. case 0: /* FIADD m32int */ /* ST(0) += m32int */
//.. DIP("fiaddl %s\n", dis_buf);
//.. fop = Iop_AddF64;
//.. loadLE(Ity_I32, mkexpr(addr))),
//.. get_ST(0)));
//.. break;
-//..
-//.. default:
-//.. vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//.. vex_printf("first_opcode == 0xDA\n");
-//.. goto decode_fail;
-//.. }
-//..
-//.. } else {
-//..
-//.. delta++;
-//.. switch (modrm) {
-//..
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xDA\n");
+ goto decode_fail;
+ }
+
+ } else {
+
+ delta++;
+ switch (modrm) {
+
//.. case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
//.. r_src = (UInt)modrm - 0xC0;
//.. DIP("fcmovb %%st(%d), %%st(0)\n", r_src);
//.. mk_x86g_calculate_condition(X86CondB)),
//.. get_ST(0), get_ST(r_src)) );
//.. break;
-//..
-//.. case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
-//.. r_src = (UInt)modrm - 0xC8;
-//.. DIP("fcmovz %%st(%d), %%st(0)\n", r_src);
-//.. put_ST_UNCHECKED(0,
-//.. IRExpr_Mux0X(
-//.. unop(Iop_1Uto8,
-//.. mk_x86g_calculate_condition(X86CondZ)),
-//.. get_ST(0), get_ST(r_src)) );
-//.. break;
-//..
+
+ case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
+ r_src = (UInt)modrm - 0xC8;
+ DIP("fcmovz %%st(%d), %%st(0)\n", r_src);
+ put_ST_UNCHECKED(0,
+ IRExpr_Mux0X(
+ unop(Iop_1Uto8,
+ mk_amd64g_calculate_condition(AMD64CondZ)),
+ get_ST(0), get_ST(r_src)) );
+ break;
+
//.. case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
//.. r_src = (UInt)modrm - 0xD0;
//.. DIP("fcmovbe %%st(%d), %%st(0)\n", r_src);
//.. fp_pop();
//.. fp_pop();
//.. break;
-//..
-//.. default:
-//.. goto decode_fail;
-//.. }
-//..
-//.. }
-//.. }
-//..
+
+ default:
+ goto decode_fail;
+ }
+
+ }
+ }
+
//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
//.. else
//.. if (first_opcode == 0xDB) {
//..
//.. }
//.. }
-//..
-//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
-//.. else
-//.. if (first_opcode == 0xDD) {
-//..
-//.. if (modrm < 0xC0) {
-//..
-//.. /* bits 5,4,3 are an opcode extension, and the modRM also
-//.. specifies an address. */
-//.. IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//.. delta += len;
-//..
-//.. switch (gregOfRM(modrm)) {
-//..
-//.. case 0: /* FLD double-real */
-//.. DIP("fldl %s\n", dis_buf);
-//.. fp_push();
-//.. put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
-//.. break;
-//..
+
+ /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
+ else
+ if (first_opcode == 0xDD) {
+
+ if (modrm < 0xC0) {
+
+ /* bits 5,4,3 are an opcode extension, and the modRM also
+ specifies an address. */
+ IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+ delta += len;
+
+ switch (gregOfRM(modrm)) {
+
+ case 0: /* FLD double-real */
+ DIP("fldl %s\n", dis_buf);
+ fp_push();
+ put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
+ break;
+
//.. case 2: /* FST double-real */
//.. DIP("fstl %s\n", dis_buf);
//.. storeLE(mkexpr(addr), get_ST(0));
//.. break;
-//..
-//.. case 3: /* FSTP double-real */
-//.. DIP("fstpl %s\n", dis_buf);
-//.. storeLE(mkexpr(addr), get_ST(0));
-//.. fp_pop();
-//.. break;
-//..
+
+ case 3: /* FSTP double-real */
+ DIP("fstpl %s\n", dis_buf);
+ storeLE(mkexpr(addr), get_ST(0));
+ fp_pop();
+ break;
+
//.. case 4: { /* FRSTOR m108 */
//.. /* Uses dirty helper:
//.. VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
//.. DIP("fnsave %s\n", dis_buf);
//.. break;
//.. }
-//..
-//.. default:
-//.. vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//.. vex_printf("first_opcode == 0xDD\n");
-//.. goto decode_fail;
-//.. }
-//.. } else {
-//.. delta++;
-//.. switch (modrm) {
-//..
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xDD\n");
+ goto decode_fail;
+ }
+ } else {
+ delta++;
+ switch (modrm) {
+
//.. case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
//.. r_dst = (UInt)modrm - 0xD0;
//.. DIP("fst %%st(0),%%st(%d)\n", r_dst);
//.. is not generated. Hence put_ST_UNCHECKED. */
//.. put_ST_UNCHECKED(r_dst, get_ST(0));
//.. break;
-//..
-//.. case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
-//.. r_dst = (UInt)modrm - 0xD8;
-//.. DIP("fstp %%st(0),%%st(%d)\n", r_dst);
-//.. /* P4 manual says: "If the destination operand is a
-//.. non-empty register, the invalid-operation exception
-//.. is not generated. Hence put_ST_UNCHECKED. */
-//.. put_ST_UNCHECKED(r_dst, get_ST(0));
-//.. fp_pop();
-//.. break;
-//..
+
+ case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
+ r_dst = (UInt)modrm - 0xD8;
+ DIP("fstp %%st(0),%%st(%d)\n", r_dst);
+ /* P4 manual says: "If the destination operand is a
+ non-empty register, the invalid-operation exception
+ is not generated. Hence put_ST_UNCHECKED. */
+ put_ST_UNCHECKED(r_dst, get_ST(0));
+ fp_pop();
+ break;
+
//.. case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
//.. r_dst = (UInt)modrm - 0xE0;
//.. DIP("fucom %%st(0),%%st(%d)\n", r_dst);
//.. ));
//.. fp_pop();
//.. break;
-//..
-//.. default:
-//.. goto decode_fail;
-//.. }
-//.. }
-//.. }
-//..
+
+ default:
+ goto decode_fail;
+ }
+ }
+ }
+
//.. /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
//.. else
//.. if (first_opcode == 0xDE) {
//.. }
//..
//.. }
-//..
-//.. else
-//.. vpanic("dis_FPU(x86): invalid primary opcode");
-//..
-//.. *decode_ok = True;
-//.. return delta;
-//..
-//.. decode_fail:
-//.. *decode_ok = False;
-//.. return delta;
-//.. }
-//..
-//..
+
+ else
+ goto decode_fail; //vpanic("dis_FPU(amd64): invalid primary opcode");
+
+ *decode_ok = True;
+ return delta;
+
+ decode_fail:
+ *decode_ok = False;
+ return delta;
+}
+
+
//.. /*------------------------------------------------------------*/
//.. /*--- ---*/
//.. /*--- MMX INSTRUCTIONS ---*/
Handles full width G = G `op` E and G = (not G) `op` E.
*/
-static UInt dis_SSE_E_to_G_all_wrk (
- Prefix pfx, ULong delta,
- HChar* opname, IROp op,
- Bool invertG
- )
+static ULong dis_SSE_E_to_G_all_wrk (
+ Prefix pfx, ULong delta,
+ HChar* opname, IROp op,
+ Bool invertG
+ )
{
HChar dis_buf[50];
Int alen;
/* All lanes SSE binary operation, G = G `op` E. */
static
-UInt dis_SSE_E_to_G_all ( Prefix pfx, ULong delta, HChar* opname, IROp op )
+ULong dis_SSE_E_to_G_all ( Prefix pfx, ULong delta,
+ HChar* opname, IROp op )
{
return dis_SSE_E_to_G_all_wrk( pfx, delta, opname, op, False );
}
-//.. /* All lanes SSE binary operation, G = (not G) `op` E. */
-//..
-//.. static
-//.. UInt dis_SSE_E_to_G_all_invG ( UChar sorb, ULong delta,
-//.. HChar* opname, IROp op )
-//.. {
-//.. return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
-//.. }
-//..
-//..
-//.. /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
-//..
-//.. static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, ULong delta,
-//.. HChar* opname, IROp op )
-//.. {
-//.. HChar dis_buf[50];
-//.. Int alen;
-//.. IRTemp addr;
-//.. UChar rm = getUChar(delta);
-//.. IRExpr* gpart = getXMMReg(gregOfRM(rm));
-//.. if (epartIsReg(rm)) {
-//.. putXMMReg( gregOfRM(rm),
-//.. binop(op, gpart,
-//.. getXMMReg(eregOfRM(rm))) );
-//.. DIP("%s %s,%s\n", opname,
-//.. nameXMMReg(eregOfRM(rm)),
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. return delta+1;
-//.. } else {
-//.. /* We can only do a 32-bit memory read, so the upper 3/4 of the
-//.. E operand needs to be made simply of zeroes. */
-//.. IRTemp epart = newTemp(Ity_V128);
-//.. addr = disAMode ( &alen, sorb, delta, dis_buf );
-//.. assign( epart, unop( Iop_32Uto128,
-//.. loadLE(Ity_I32, mkexpr(addr))) );
-//.. putXMMReg( gregOfRM(rm),
-//.. binop(op, gpart, mkexpr(epart)) );
-//.. DIP("%s %s,%s\n", opname,
-//.. dis_buf,
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. return delta+alen;
-//.. }
-//.. }
+/* All lanes SSE binary operation, G = (not G) `op` E. */
+
+static
+ULong dis_SSE_E_to_G_all_invG ( Prefix pfx, ULong delta,
+ HChar* opname, IROp op )
+{
+ return dis_SSE_E_to_G_all_wrk( pfx, delta, opname, op, True );
+}
+
+
+/* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
+
+static ULong dis_SSE_E_to_G_lo32 ( Prefix pfx, ULong delta,
+ HChar* opname, IROp op )
+{
+ HChar dis_buf[50];
+ Int alen;
+ IRTemp addr;
+ UChar rm = getUChar(delta);
+ IRExpr* gpart = getXMMReg(gregOfRM(rm));
+ if (epartIsReg(rm)) {
+ putXMMReg( gregOfRM(rm),
+ binop(op, gpart,
+ getXMMReg(eregOfRexRM(pfx,rm))) );
+ DIP("%s %s,%s\n", opname,
+ nameXMMReg(eregOfRexRM(pfx,rm)),
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ return delta+1;
+ } else {
+ /* We can only do a 32-bit memory read, so the upper 3/4 of the
+ E operand needs to be made simply of zeroes. */
+ IRTemp epart = newTemp(Ity_V128);
+ addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
+ assign( epart, unop( Iop_32UtoV128,
+ loadLE(Ity_I32, mkexpr(addr))) );
+ putXMMReg( gregOfRexRM(pfx,rm),
+ binop(op, gpart, mkexpr(epart)) );
+ DIP("%s %s,%s\n", opname,
+ dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ return delta+alen;
+ }
+}
/* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
-static UInt dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta,
- HChar* opname, IROp op )
+static ULong dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta,
+ HChar* opname, IROp op )
{
HChar dis_buf[50];
Int alen;
/* Lowest 64-bit lane only unary SSE operation, G = op(E). */
-static UInt dis_SSE_E_to_G_unary_lo64 (
- Prefix pfx, ULong delta,
- HChar* opname, IROp op
- )
+static ULong dis_SSE_E_to_G_unary_lo64 (
+ Prefix pfx, ULong delta,
+ HChar* opname, IROp op
+ )
{
/* First we need to get the old G value and patch the low 64 bits
of the E operand into it. Then apply op and write back to G. */
//.. : binop(op, gpart, epart) );
//.. return delta;
//.. }
-//..
-//..
-//.. /* Helper for doing SSE FP comparisons. */
-//..
-//.. static void findSSECmpOp ( Bool* needNot, IROp* op,
-//.. Int imm8, Bool all_lanes, Int sz )
-//.. {
-//.. imm8 &= 7;
-//.. *needNot = False;
-//.. *op = Iop_INVALID;
-//.. if (imm8 >= 4) {
-//.. *needNot = True;
-//.. imm8 -= 4;
-//.. }
-//..
-//.. if (sz == 4 && all_lanes) {
-//.. switch (imm8) {
-//.. case 0: *op = Iop_CmpEQ32Fx4; return;
-//.. case 1: *op = Iop_CmpLT32Fx4; return;
-//.. case 2: *op = Iop_CmpLE32Fx4; return;
-//.. case 3: *op = Iop_CmpUN32Fx4; return;
-//.. default: break;
-//.. }
-//.. }
-//.. if (sz == 4 && !all_lanes) {
-//.. switch (imm8) {
-//.. case 0: *op = Iop_CmpEQ32F0x4; return;
-//.. case 1: *op = Iop_CmpLT32F0x4; return;
-//.. case 2: *op = Iop_CmpLE32F0x4; return;
-//.. case 3: *op = Iop_CmpUN32F0x4; return;
-//.. default: break;
-//.. }
-//.. }
-//.. if (sz == 8 && all_lanes) {
-//.. switch (imm8) {
-//.. case 0: *op = Iop_CmpEQ64Fx2; return;
-//.. case 1: *op = Iop_CmpLT64Fx2; return;
-//.. case 2: *op = Iop_CmpLE64Fx2; return;
-//.. case 3: *op = Iop_CmpUN64Fx2; return;
-//.. default: break;
-//.. }
-//.. }
-//.. if (sz == 8 && !all_lanes) {
-//.. switch (imm8) {
-//.. case 0: *op = Iop_CmpEQ64F0x2; return;
-//.. case 1: *op = Iop_CmpLT64F0x2; return;
-//.. case 2: *op = Iop_CmpLE64F0x2; return;
-//.. case 3: *op = Iop_CmpUN64F0x2; return;
-//.. default: break;
-//.. }
-//.. }
-//.. vpanic("findSSECmpOp(x86,guest)");
-//.. }
-//..
-//.. /* Handles SSE 32F comparisons. */
-//..
-//.. static UInt dis_SSEcmp_E_to_G ( UChar sorb, ULong delta,
-//.. HChar* opname, Bool all_lanes, Int sz )
-//.. {
-//.. HChar dis_buf[50];
-//.. Int alen, imm8;
-//.. IRTemp addr;
-//.. Bool needNot = False;
-//.. IROp op = Iop_INVALID;
-//.. IRTemp plain = newTemp(Ity_V128);
-//.. UChar rm = getUChar(delta);
-//.. UShort mask = 0;
-//.. vassert(sz == 4 || sz == 8);
-//.. if (epartIsReg(rm)) {
-//.. imm8 = getUChar(delta+1);
-//.. findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
-//.. assign( plain, binop(op, getXMMReg(gregOfRM(rm)),
-//.. getXMMReg(eregOfRM(rm))) );
-//.. delta += 2;
-//.. DIP("%s $%d,%s,%s\n", opname,
-//.. (Int)imm8,
-//.. nameXMMReg(eregOfRM(rm)),
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta, dis_buf );
-//.. imm8 = getUChar(delta+alen);
-//.. findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
-//.. assign( plain, binop(op, getXMMReg(gregOfRM(rm)),
-//.. loadLE(Ity_V128, mkexpr(addr))) );
-//.. delta += alen+1;
-//.. DIP("%s $%d,%s,%s\n", opname,
-//.. (Int)imm8,
-//.. dis_buf,
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. }
-//..
-//.. if (needNot && all_lanes) {
-//.. putXMMReg( gregOfRM(rm),
-//.. unop(Iop_Not128, mkexpr(plain)) );
-//.. }
-//.. else
-//.. if (needNot && !all_lanes) {
-//.. mask = sz==4 ? 0x000F : 0x00FF;
-//.. putXMMReg( gregOfRM(rm),
-//.. binop(Iop_Xor128, mkexpr(plain), mkV128(mask)) );
-//.. }
-//.. else {
-//.. putXMMReg( gregOfRM(rm), mkexpr(plain) );
-//.. }
-//..
-//.. return delta;
-//.. }
-//..
-//..
+
+
+/* Helper for doing SSE FP comparisons. */
+
+static void findSSECmpOp ( Bool* needNot, IROp* op,
+ Int imm8, Bool all_lanes, Int sz )
+{
+ imm8 &= 7;
+ *needNot = False;
+ *op = Iop_INVALID;
+ if (imm8 >= 4) {
+ *needNot = True;
+ imm8 -= 4;
+ }
+
+ if (sz == 4 && all_lanes) {
+ switch (imm8) {
+ case 0: *op = Iop_CmpEQ32Fx4; return;
+ case 1: *op = Iop_CmpLT32Fx4; return;
+ case 2: *op = Iop_CmpLE32Fx4; return;
+ case 3: *op = Iop_CmpUN32Fx4; return;
+ default: break;
+ }
+ }
+ if (sz == 4 && !all_lanes) {
+ switch (imm8) {
+ case 0: *op = Iop_CmpEQ32F0x4; return;
+ case 1: *op = Iop_CmpLT32F0x4; return;
+ case 2: *op = Iop_CmpLE32F0x4; return;
+ case 3: *op = Iop_CmpUN32F0x4; return;
+ default: break;
+ }
+ }
+ if (sz == 8 && all_lanes) {
+ switch (imm8) {
+ case 0: *op = Iop_CmpEQ64Fx2; return;
+ case 1: *op = Iop_CmpLT64Fx2; return;
+ case 2: *op = Iop_CmpLE64Fx2; return;
+ case 3: *op = Iop_CmpUN64Fx2; return;
+ default: break;
+ }
+ }
+ if (sz == 8 && !all_lanes) {
+ switch (imm8) {
+ case 0: *op = Iop_CmpEQ64F0x2; return;
+ case 1: *op = Iop_CmpLT64F0x2; return;
+ case 2: *op = Iop_CmpLE64F0x2; return;
+ case 3: *op = Iop_CmpUN64F0x2; return;
+ default: break;
+ }
+ }
+ vpanic("findSSECmpOp(amd64,guest)");
+}
+
+/* Handles SSE 32F comparisons. */
+
+static ULong dis_SSEcmp_E_to_G ( Prefix pfx, ULong delta,
+ HChar* opname, Bool all_lanes, Int sz )
+{
+ HChar dis_buf[50];
+ Int alen, imm8;
+ IRTemp addr;
+ Bool needNot = False;
+ IROp op = Iop_INVALID;
+ IRTemp plain = newTemp(Ity_V128);
+ UChar rm = getUChar(delta);
+ UShort mask = 0;
+ vassert(sz == 4 || sz == 8);
+ if (epartIsReg(rm)) {
+ imm8 = getUChar(delta+1);
+ findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+ assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)),
+ getXMMReg(eregOfRexRM(pfx,rm))) );
+ delta += 2;
+ DIP("%s $%d,%s,%s\n", opname,
+ (Int)imm8,
+ nameXMMReg(eregOfRexRM(pfx,rm)),
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ } else {
+ addr = disAMode ( &alen, pfx, delta, dis_buf, 1 );
+ imm8 = getUChar(delta+alen);
+ findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+ assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)),
+ loadLE(Ity_V128, mkexpr(addr))) );
+ delta += alen+1;
+ DIP("%s $%d,%s,%s\n", opname,
+ (Int)imm8,
+ dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ }
+
+ if (needNot && all_lanes) {
+ putXMMReg( gregOfRM(rm),
+ unop(Iop_NotV128, mkexpr(plain)) );
+ }
+ else
+ if (needNot && !all_lanes) {
+ mask = sz==4 ? 0x000F : 0x00FF;
+ putXMMReg( gregOfRexRM(pfx,rm),
+ binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
+ }
+ else {
+ putXMMReg( gregOfRexRM(pfx,rm), mkexpr(plain) );
+ }
+
+ return delta;
+}
+
+
//.. /* Vector by scalar shift of G by the amount specified at the bottom
//.. of E. */
//..
//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
//.. goto decode_success;
//.. }
-//..
-//.. /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x58) {
-//.. vassert(sz == 4);
-//.. delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "addss", Iop_Add32F0x4 );
-//.. goto decode_success;
-//.. }
-//..
+
+ /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
+ if (haveF3no66noF2(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x58) {
+ delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "addss", Iop_Add32F0x4 );
+ goto decode_success;
+ }
+
//.. /* 0F 55 = ANDNPS -- G = (not G) and E */
//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
//.. delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_And128 );
//.. nameXMMReg(gregOfRM(modrm)));
//.. } else {
//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//.. assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//.. assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
//.. delta += 2+alen;
//.. DIP("cvtpi2ps %s,%s\n", dis_buf,
//.. nameXMMReg(gregOfRM(modrm)) );
//.. unop(Iop_64to32, mkexpr(arg64)) )) );
//..
//.. putXMMRegLane32F(
-//.. gregOfRM(modrm), 1,
-//.. binop(Iop_F64toF32,
-//.. mkexpr(rmode),
-//.. unop(Iop_I32toF64,
-//.. unop(Iop_64HIto32, mkexpr(arg64)) )) );
-//..
-//.. goto decode_success;
-//.. }
-//..
-//.. /* F3 0F 2A = CVTSI2SS -- convert I32 in mem/ireg to F32 in low
-//.. quarter xmm */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
-//.. IRTemp arg32 = newTemp(Ity_I32);
-//.. IRTemp rmode = newTemp(Ity_I32);
-//.. vassert(sz == 4);
-//..
-//.. modrm = getUChar(delta+3);
-//.. if (epartIsReg(modrm)) {
-//.. assign( arg32, getIReg(4, eregOfRM(modrm)) );
-//.. delta += 3+1;
-//.. DIP("cvtsi2ss %s,%s\n", nameIReg(4, eregOfRM(modrm)),
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//.. assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
-//.. delta += 3+alen;
-//.. DIP("cvtsi2ss %s,%s\n", dis_buf,
-//.. nameXMMReg(gregOfRM(modrm)) );
-//.. }
-//..
-//.. assign( rmode, get_sse_roundingmode() );
-//..
-//.. putXMMRegLane32F(
-//.. gregOfRM(modrm), 0,
-//.. binop(Iop_F64toF32,
+//.. gregOfRM(modrm), 1,
+//.. binop(Iop_F64toF32,
//.. mkexpr(rmode),
-//.. unop(Iop_I32toF64, mkexpr(arg32)) ) );
+//.. unop(Iop_I32toF64,
+//.. unop(Iop_64HIto32, mkexpr(arg64)) )) );
//..
//.. goto decode_success;
//.. }
-//..
+
+ /* F3 0F 2A = CVTSI2SS
+ -- sz==4: convert I32 in mem/ireg to F32 in low quarter xmm
+ -- sz==8: convert I64 in mem/ireg to F32 in low quarter xmm */
+ if (haveF3no66noF2(pfx) && (sz == 4 || sz == 8)
+ && insn[0] == 0x0F && insn[1] == 0x2A) {
+
+ IRTemp rmode = newTemp(Ity_I32);
+ assign( rmode, get_sse_roundingmode() );
+ modrm = getUChar(delta+2);
+
+ if (sz == 4) {
+ IRTemp arg32 = newTemp(Ity_I32);
+ if (epartIsReg(modrm)) {
+ goto decode_failure; /* awaiting test case */
+ assign( arg32, getIRegB(pfx, 4, eregOfRM(modrm)) );
+ delta += 2+1;
+ DIP("cvtsi2ss %s,%s\n", nameIRegB(pfx, 4, eregOfRM(modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ } else {
+ goto decode_failure; /* awaiting test case */
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
+ delta += 2+alen;
+ DIP("cvtsi2ss %s,%s\n", dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)) );
+ }
+ putXMMRegLane32F(
+ gregOfRexRM(pfx,modrm), 0,
+ binop(Iop_F64toF32,
+ mkexpr(rmode),
+ unop(Iop_I32toF64, mkexpr(arg32)) ) );
+ } else {
+ /* sz == 8 */
+ IRTemp arg64 = newTemp(Ity_I64);
+ if (epartIsReg(modrm)) {
+ assign( arg64, getIRegB(pfx, 8, eregOfRM(modrm)) );
+ delta += 2+1;
+ DIP("cvtsi2ssq %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ } else {
+ goto decode_failure; /* awaiting test case */
+ }
+ putXMMRegLane32F(
+ gregOfRexRM(pfx,modrm), 0,
+ binop(Iop_F64toF32,
+ mkexpr(rmode),
+ binop(Iop_I64toF64, mkexpr(rmode), mkexpr(arg64)) ) );
+ }
+
+ goto decode_success;
+ }
+
//.. /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
//.. I32 in mmx, according to prevailing SSE rounding mode */
//.. /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
//.. delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "minss", Iop_Min32F0x4 );
//.. goto decode_success;
//.. }
-//..
-//.. /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
-//.. /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
-//.. if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
-//.. modrm = getUChar(delta+2);
-//.. if (epartIsReg(modrm)) {
-//.. putXMMReg( gregOfRM(modrm),
-//.. getXMMReg( eregOfRM(modrm) ));
-//.. DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 2+1;
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//.. putXMMReg( gregOfRM(modrm),
-//.. loadLE(Ity_V128, mkexpr(addr)) );
-//.. DIP("mov[ua]ps %s,%s\n", dis_buf,
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 2+alen;
-//.. }
-//.. goto decode_success;
-//.. }
+
+ /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
+ /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
+ if (haveNo66noF2noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
+ modrm = getUChar(delta+2);
+ if (epartIsReg(modrm)) {
+ putXMMReg( gregOfRexRM(pfx,modrm),
+ getXMMReg( eregOfRexRM(pfx,modrm) ));
+ DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+1;
+ } else {
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ putXMMReg( gregOfRexRM(pfx,modrm),
+ loadLE(Ity_V128, mkexpr(addr)) );
+ DIP("mov[ua]ps %s,%s\n", dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+alen;
+ }
+ goto decode_success;
+ }
/* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
- if (haveNo66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x29) {
+ if (haveNo66noF2noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x29) {
modrm = getUChar(delta+2);
if (epartIsReg(modrm)) {
/* fall through; awaiting test case */
//.. }
//.. /* else fall through */
//.. }
-//..
-//.. /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
-//.. (lo 1/4 xmm). If E is mem, upper 3/4 of G is zeroed out. */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x10) {
-//.. vassert(sz == 4);
-//.. modrm = getUChar(delta+3);
-//.. if (epartIsReg(modrm)) {
-//.. putXMMRegLane32( gregOfRM(modrm), 0,
-//.. getXMMRegLane32( eregOfRM(modrm), 0 ));
-//.. DIP("movss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 3+1;
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//.. putXMMReg( gregOfRM(modrm), mkV128(0) );
-//.. putXMMRegLane32( gregOfRM(modrm), 0,
-//.. loadLE(Ity_I32, mkexpr(addr)) );
-//.. DIP("movss %s,%s\n", dis_buf,
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 3+alen;
-//.. }
-//.. goto decode_success;
-//.. }
-//..
-//.. /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
-//.. or lo 1/4 xmm). */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
-//.. vassert(sz == 4);
-//.. modrm = getUChar(delta+3);
-//.. if (epartIsReg(modrm)) {
-//.. /* fall through, we don't yet have a test case */
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//.. storeLE( mkexpr(addr),
-//.. getXMMRegLane32(gregOfRM(modrm), 0) );
-//.. DIP("movss %s,%s\n", nameXMMReg(gregOfRM(modrm)),
-//.. dis_buf);
-//.. delta += 3+alen;
-//.. goto decode_success;
-//.. }
-//.. }
-//..
+
+ /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
+ (lo 1/4 xmm). If E is mem, upper 3/4 of G is zeroed out. */
+ if (haveF3no66noF2(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x10) {
+ modrm = getUChar(delta+2);
+ if (epartIsReg(modrm)) {
+ putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
+ getXMMRegLane32( eregOfRexRM(pfx,modrm), 0 ));
+ DIP("movss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+1;
+ } else {
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
+ putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
+ loadLE(Ity_I32, mkexpr(addr)) );
+ DIP("movss %s,%s\n", dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+alen;
+ }
+ goto decode_success;
+ }
+
+ /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
+ or lo 1/4 xmm). */
+ if (haveF3no66noF2(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x11) {
+ modrm = getUChar(delta+2);
+ if (epartIsReg(modrm)) {
+ /* fall through, we don't yet have a test case */
+ } else {
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ storeLE( mkexpr(addr),
+ getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
+ DIP("movss %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
+ dis_buf);
+ delta += 2+alen;
+ goto decode_success;
+ }
+ }
+
//.. /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x59) {
//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulps", Iop_Mul32Fx4 );
//.. goto decode_success;
//.. }
-//..
-//.. /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x59) {
-//.. vassert(sz == 4);
-//.. delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "mulss", Iop_Mul32F0x4 );
-//.. goto decode_success;
-//.. }
-//..
+
+ /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
+ if (haveF3no66noF2(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x59) {
+ delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "mulss", Iop_Mul32F0x4 );
+ goto decode_success;
+ }
+
//.. /* 0F 56 = ORPS -- G = G and E */
//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x56) {
//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "orps", Iop_Or128 );
//.. } else {
//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf );
//.. assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
-//.. order = (Int)insn[2+alen];
+//.. order = (Int)insn[2+alen];
//.. delta += 3+alen;
//.. DIP("pshufw $%d,%s,%s\n", order,
//.. dis_buf,
//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );
//.. goto decode_success;
//.. }
-//..
-//.. /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
-//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5C) {
-//.. vassert(sz == 4);
-//.. delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "subss", Iop_Sub32F0x4 );
-//.. goto decode_success;
-//.. }
-//..
+
+ /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
+ if (haveF3no66noF2(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x5C) {
+ delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "subss", Iop_Sub32F0x4 );
+ goto decode_success;
+ }
+
//.. /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
//.. /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
//.. /* These just appear to be special cases of SHUFPS */
//..
//.. goto decode_success;
//.. }
-//..
-//.. /* 0F 57 = XORPS -- G = G and E */
-//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x57) {
-//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorps", Iop_Xor128 );
-//.. goto decode_success;
-//.. }
-//..
+
+ /* 0F 57 = XORPS -- G = G and E */
+ if (haveNo66noF2noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x57) {
+ delta = dis_SSE_E_to_G_all( pfx, delta+2, "xorps", Iop_XorV128 );
+ goto decode_success;
+ }
+
//.. /* ---------------------------------------------------- */
//.. /* --- end of the SSE decoder. --- */
//.. /* ---------------------------------------------------- */
goto decode_success;
}
-//.. /* 66 0F 55 = ANDNPD -- G = (not G) and E */
-//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
-//.. delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_And128 );
-//.. goto decode_success;
-//.. }
+ /* 66 0F 55 = ANDNPD -- G = (not G) and E */
+ if (have66noF2noF3(pfx) && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x55) {
+ delta = dis_SSE_E_to_G_all_invG( pfx, delta+2, "andnpd", Iop_AndV128 );
+ goto decode_success;
+ }
/* 66 0F 54 = ANDPD -- G = G and E */
if (have66noF2noF3(pfx) && sz == 2
//.. delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmppd", True, 8 );
//.. goto decode_success;
//.. }
-//..
-//.. /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
-//.. if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
-//.. vassert(sz == 4);
-//.. delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpsd", False, 8 );
-//.. goto decode_success;
-//.. }
+
+ /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
+ if (haveF2no66noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0xC2) {
+ delta = dis_SSEcmp_E_to_G( pfx, delta+2, "cmpsd", False, 8 );
+ goto decode_success;
+ }
/* 66 0F 2F = COMISD -- 64F0x2 comparison G,E, and set ZCP */
/* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
//.. nameXMMReg(gregOfRM(modrm)));
//.. } else {
//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//.. assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//.. assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
//.. delta += 3+alen;
//.. DIP("cvtdq2pd %s,%s\n", dis_buf,
//.. nameXMMReg(gregOfRM(modrm)) );
goto decode_success;
}
-//.. /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
-//.. low 1/4 xmm(G), according to prevailing SSE rounding mode */
-//.. if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
-//.. IRTemp rmode = newTemp(Ity_I32);
-//.. IRTemp f64lo = newTemp(Ity_F64);
-//.. vassert(sz == 4);
-//..
-//.. modrm = getUChar(delta+3);
-//.. if (epartIsReg(modrm)) {
-//.. delta += 3+1;
-//.. assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
-//.. DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//.. assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
-//.. delta += 3+alen;
-//.. DIP("cvtsd2ss %s,%s\n", dis_buf,
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. }
-//..
-//.. assign( rmode, get_sse_roundingmode() );
-//.. putXMMRegLane32F(
-//.. gregOfRM(modrm), 0,
-//.. binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
-//.. );
-//..
-//.. goto decode_success;
-//.. }
+ /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
+ low 1/4 xmm(G), according to prevailing SSE rounding mode */
+ if (haveF2no66noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x5A) {
+ IRTemp rmode = newTemp(Ity_I32);
+ IRTemp f64lo = newTemp(Ity_F64);
+ vassert(sz == 4);
+
+ modrm = getUChar(delta+2);
+ if (epartIsReg(modrm)) {
+ delta += 2+1;
+ assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
+ DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ } else {
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
+ delta += 2+alen;
+ DIP("cvtsd2ss %s,%s\n", dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ }
+
+ assign( rmode, get_sse_roundingmode() );
+ putXMMRegLane32F(
+ gregOfRexRM(pfx,modrm), 0,
+ binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
+ );
+
+ goto decode_success;
+ }
/* F2 0F 2A = CVTSI2SD
when sz==4 -- convert I32 in mem/ireg to F64 in low half xmm
when sz==8 -- convert I64 in mem/ireg to F64 in low half xmm
*/
- if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x2A) {
- vassert(sz == 4 || sz == 8);
+ if (haveF2no66noF3(pfx) && (sz == 4 || sz == 8)
+ && insn[0] == 0x0F && insn[1] == 0x2A) {
modrm = getUChar(delta+2);
if (sz == 4) {
if (epartIsReg(modrm)) {
assign( arg64, getIRegB(pfx, 8, eregOfRM(modrm)) );
delta += 2+1;
- DIP("cvtsi2sd %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
- nameXMMReg(gregOfRexRM(pfx,modrm)));
+ DIP("cvtsi2sdq %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
} else {
addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
delta += 2+alen;
- DIP("cvtsi2sd %s,%s\n", dis_buf,
- nameXMMReg(gregOfRexRM(pfx,modrm)) );
+ DIP("cvtsi2sdq %s,%s\n", dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)) );
}
putXMMRegLane64F(
gregOfRexRM(pfx,modrm),
//.. delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
//.. goto decode_success;
//.. }
-//..
-//.. /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
-//.. /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
-//.. /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
-//.. if (sz == 2 && insn[0] == 0x0F
-//.. && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
-//.. HChar* wot = insn[1]==0x28 ? "apd" :
-//.. insn[1]==0x10 ? "upd" : "dqa";
-//.. modrm = getUChar(delta+2);
-//.. if (epartIsReg(modrm)) {
-//.. putXMMReg( gregOfRM(modrm),
-//.. getXMMReg( eregOfRM(modrm) ));
-//.. DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRM(modrm)),
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 2+1;
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//.. putXMMReg( gregOfRM(modrm),
-//.. loadLE(Ity_V128, mkexpr(addr)) );
-//.. DIP("mov%s %s,%s\n", wot, dis_buf,
-//.. nameXMMReg(gregOfRM(modrm)));
-//.. delta += 2+alen;
-//.. }
-//.. goto decode_success;
-//.. }
-//..
+
+ /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
+ /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
+ /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
+ if (have66noF2noF3(pfx) && sz == 2
+ && insn[0] == 0x0F
+ && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
+ HChar* wot = insn[1]==0x28 ? "apd" :
+ insn[1]==0x10 ? "upd" : "dqa";
+ modrm = getUChar(delta+2);
+ if (epartIsReg(modrm)) {
+ putXMMReg( gregOfRexRM(pfx,modrm),
+ getXMMReg( eregOfRexRM(pfx,modrm) ));
+ DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRexRM(pfx,modrm)),
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+1;
+ } else {
+ addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+ putXMMReg( gregOfRexRM(pfx,modrm),
+ loadLE(Ity_V128, mkexpr(addr)) );
+ DIP("mov%s %s,%s\n", wot, dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,modrm)));
+ delta += 2+alen;
+ }
+ goto decode_success;
+ }
+
//.. /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x29) {
//.. modrm = getUChar(delta+2);
/* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
or lo half xmm). */
- if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x11) {
- vassert(sz == 4);
+ if (haveF2no66noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x11) {
modrm = getUChar(delta+2);
if (epartIsReg(modrm)) {
/* fall through, we don't yet have a test case */
//.. }
/* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
- if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x59) {
- vassert(sz == 4);
+ if (haveF2no66noF3(pfx) && sz == 4
+ && insn[0] == 0x0F && insn[1] == 0x59) {
delta = dis_SSE_E_to_G_lo64( pfx, delta+2, "mulsd", Iop_Mul64F0x2 );
goto decode_success;
}
-//.. /* 66 0F 56 = ORPD -- G = G and E */
-//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x56) {
-//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "orpd", Iop_Or128 );
-//.. goto decode_success;
-//.. }
-//..
+ /* 66 0F 56 = ORPD -- G = G and E */
+ if (have66noF2noF3(pfx) && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x56) {
+ delta = dis_SSE_E_to_G_all( pfx, delta+2, "orpd", Iop_OrV128 );
+ goto decode_success;
+ }
+
//.. /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
//.. Int select;
: "cqo\n"));
break;
-//.. /* ------------------------ FPU ops -------------------- */
-//..
+ /* ------------------------ FPU ops -------------------- */
+
//.. case 0x9E: /* SAHF */
//.. codegen_SAHF();
//.. DIP("sahf\n");
//.. /* ignore? */
//.. DIP("fwait\n");
//.. break;
-//..
-//.. case 0xD8:
-//.. case 0xD9:
-//.. case 0xDA:
-//.. case 0xDB:
-//.. case 0xDC:
-//.. case 0xDD:
-//.. case 0xDE:
-//.. case 0xDF: {
-//.. ULong delta0 = delta;
-//.. Bool decode_OK = False;
-//.. delta = dis_FPU ( &decode_OK, sorb, delta );
-//.. if (!decode_OK) {
-//.. delta = delta0;
-//.. goto decode_failure;
-//.. }
-//.. break;
-//.. }
-//..
+
+ case 0xD8:
+ case 0xD9:
+ case 0xDA:
+ case 0xDB:
+ case 0xDC:
+ case 0xDD:
+ case 0xDE:
+ case 0xDF:
+ if (sz == 4 && haveNo66noF2noF3(pfx)) {
+ ULong delta0 = delta;
+ Bool decode_OK = False;
+ delta = dis_FPU ( &decode_OK, pfx, delta );
+ if (!decode_OK) {
+ delta = delta0;
+ goto decode_failure;
+ }
+ break;
+ } else {
+ goto decode_failure;
+ }
+
//.. /* ------------------------ INC & DEC ------------------ */
//..
//.. case 0x40: /* INC eAX */
case 0x90: /* XCHG eAX,eAX */
if (haveF2orF3(pfx)) goto decode_failure;
- if (sz == 2 || sz == 4 || sz == 8) {
- DIP("nop\n");
- break;
- }
- /* else fall through */
+ DIP("nop\n");
+ break;
case 0x91: /* XCHG rAX,rCX */
case 0x92: /* XCHG rAX,rDX */
case 0x93: /* XCHG rAX,rBX */
case Asse_DIVF: return "div";
case Asse_MAXF: return "max";
case Asse_MINF: return "min";
-//.. case Xsse_CMPEQF: return "cmpFeq";
-//.. case Xsse_CMPLTF: return "cmpFlt";
-//.. case Xsse_CMPLEF: return "cmpFle";
-//.. case Xsse_CMPUNF: return "cmpFun";
+ case Asse_CMPEQF: return "cmpFeq";
+ case Asse_CMPLTF: return "cmpFlt";
+ case Asse_CMPLEF: return "cmpFle";
+ case Asse_CMPUNF: return "cmpFun";
//.. case Xsse_RCPF: return "rcp";
//.. case Xsse_RSQRTF: return "rsqrt";
case Asse_SQRTF: return "sqrt";
vassert(szD == 4 || szD == 8);
return i;
}
+AMD64Instr* AMD64Instr_SseSDSS ( Bool from64, HReg src, HReg dst )
+{
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_SseSDSS;
+ i->Ain.SseSDSS.from64 = from64;
+ i->Ain.SseSDSS.src = src;
+ i->Ain.SseSDSS.dst = dst;
+ return i;
+}
+
//.. AMD64Instr* AMD64Instr_SseConst ( UShort con, HReg dst ) {
//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
//.. i->tag = Xin_SseConst;
vassert(sz == 4 || sz == 8);
return i;
}
-//.. AMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
-//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
-//.. i->tag = Xin_Sse32Fx4;
-//.. i->Xin.Sse32Fx4.op = op;
-//.. i->Xin.Sse32Fx4.src = src;
-//.. i->Xin.Sse32Fx4.dst = dst;
-//.. vassert(op != Xsse_MOV);
-//.. return i;
-//.. }
-//.. AMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
-//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
-//.. i->tag = Xin_Sse32FLo;
-//.. i->Xin.Sse32FLo.op = op;
-//.. i->Xin.Sse32FLo.src = src;
-//.. i->Xin.Sse32FLo.dst = dst;
-//.. vassert(op != Xsse_MOV);
-//.. return i;
-//.. }
+AMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_Sse32Fx4;
+ i->Ain.Sse32Fx4.op = op;
+ i->Ain.Sse32Fx4.src = src;
+ i->Ain.Sse32Fx4.dst = dst;
+ vassert(op != Asse_MOV);
+ return i;
+}
+AMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_Sse32FLo;
+ i->Ain.Sse32FLo.op = op;
+ i->Ain.Sse32FLo.src = src;
+ i->Ain.Sse32FLo.dst = dst;
+ vassert(op != Asse_MOV);
+ return i;
+}
//.. AMD64Instr* AMD64Instr_Sse64Fx2 ( AMD64SseOp op, HReg src, HReg dst ) {
//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
//.. i->tag = Xin_Sse64Fx2;
i->Ain.SseReRg.dst = rg;
return i;
}
-//.. AMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
-//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
-//.. i->tag = Xin_SseCMov;
-//.. i->Xin.SseCMov.cond = cond;
-//.. i->Xin.SseCMov.src = src;
-//.. i->Xin.SseCMov.dst = dst;
-//.. vassert(cond != Xcc_ALWAYS);
-//.. return i;
-//.. }
+AMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_SseCMov;
+ i->Ain.SseCMov.cond = cond;
+ i->Ain.SseCMov.src = src;
+ i->Ain.SseCMov.dst = dst;
+ vassert(cond != Acc_ALWAYS);
+ return i;
+}
//.. AMD64Instr* AMD64Instr_SseShuf ( Int order, HReg src, HReg dst ) {
//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
//.. i->tag = Xin_SseShuf;
(i->Ain.SseSF2SI.szD==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
(i->Ain.SseSF2SI.dst);
break;
+ case Ain_SseSDSS:
+ vex_printf(i->Ain.SseSDSS.from64 ? "cvtsd2ss " : "cvtss2sd ");
+ ppHRegAMD64(i->Ain.SseSDSS.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.SseSDSS.dst);
+ break;
//.. case Xin_SseConst:
//.. vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
//.. ppHRegAMD64(i->Xin.SseConst.dst);
vex_printf(",");
ppHRegAMD64(i->Ain.SseLdzLO.reg);
return;
-//.. case Xin_Sse32Fx4:
-//.. vex_printf("%sps ", showAMD64SseOp(i->Xin.Sse32Fx4.op));
-//.. ppHRegAMD64(i->Xin.Sse32Fx4.src);
-//.. vex_printf(",");
-//.. ppHRegAMD64(i->Xin.Sse32Fx4.dst);
-//.. return;
-//.. case Xin_Sse32FLo:
-//.. vex_printf("%sss ", showAMD64SseOp(i->Xin.Sse32FLo.op));
-//.. ppHRegAMD64(i->Xin.Sse32FLo.src);
-//.. vex_printf(",");
-//.. ppHRegAMD64(i->Xin.Sse32FLo.dst);
-//.. return;
+ case Ain_Sse32Fx4:
+ vex_printf("%sps ", showAMD64SseOp(i->Ain.Sse32Fx4.op));
+ ppHRegAMD64(i->Ain.Sse32Fx4.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.Sse32Fx4.dst);
+ return;
+ case Ain_Sse32FLo:
+ vex_printf("%sss ", showAMD64SseOp(i->Ain.Sse32FLo.op));
+ ppHRegAMD64(i->Ain.Sse32FLo.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.Sse32FLo.dst);
+ return;
//.. case Xin_Sse64Fx2:
//.. vex_printf("%spd ", showAMD64SseOp(i->Xin.Sse64Fx2.op));
//.. ppHRegAMD64(i->Xin.Sse64Fx2.src);
vex_printf(",");
ppHRegAMD64(i->Ain.SseReRg.dst);
return;
-//.. case Xin_SseCMov:
-//.. vex_printf("cmov%s ", showAMD64CondCode(i->Xin.SseCMov.cond));
-//.. ppHRegAMD64(i->Xin.SseCMov.src);
-//.. vex_printf(",");
-//.. ppHRegAMD64(i->Xin.SseCMov.dst);
-//.. return;
+ case Ain_SseCMov:
+ vex_printf("cmov%s ", showAMD64CondCode(i->Ain.SseCMov.cond));
+ ppHRegAMD64(i->Ain.SseCMov.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.SseCMov.dst);
+ return;
//.. case Xin_SseShuf:
//.. vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
//.. ppHRegAMD64(i->Xin.SseShuf.src);
addHRegUse(u, HRmRead, i->Ain.SseSF2SI.src);
addHRegUse(u, HRmWrite, i->Ain.SseSF2SI.dst);
return;
+ case Ain_SseSDSS:
+ addHRegUse(u, HRmRead, i->Ain.SseSDSS.src);
+ addHRegUse(u, HRmWrite, i->Ain.SseSDSS.dst);
+ return;
case Ain_SseLdSt:
addRegUsage_AMD64AMode(u, i->Ain.SseLdSt.addr);
addHRegUse(u, i->Ain.SseLdSt.isLoad ? HRmWrite : HRmRead,
//.. case Xin_SseConst:
//.. addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
//.. return;
-//.. case Xin_Sse32Fx4:
-//.. vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
-//.. unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
-//.. || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
-//.. || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
-//.. addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
-//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
-//.. i->Xin.Sse32Fx4.dst);
-//.. return;
-//.. case Xin_Sse32FLo:
-//.. vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
-//.. unary = i->Xin.Sse32FLo.op == Xsse_RCPF
-//.. || i->Xin.Sse32FLo.op == Xsse_RSQRTF
-//.. || i->Xin.Sse32FLo.op == Xsse_SQRTF;
-//.. addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
-//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
-//.. i->Xin.Sse32FLo.dst);
-//.. return;
+ case Ain_Sse32Fx4:
+ vassert(i->Ain.Sse32Fx4.op != Asse_MOV);
+ unary = i->Ain.Sse32Fx4.op == Asse_RCPF
+ || i->Ain.Sse32Fx4.op == Asse_RSQRTF
+ || i->Ain.Sse32Fx4.op == Asse_SQRTF;
+ addHRegUse(u, HRmRead, i->Ain.Sse32Fx4.src);
+ addHRegUse(u, unary ? HRmWrite : HRmModify,
+ i->Ain.Sse32Fx4.dst);
+ return;
+ case Ain_Sse32FLo:
+ vassert(i->Ain.Sse32FLo.op != Asse_MOV);
+ unary = i->Ain.Sse32FLo.op == Asse_RCPF
+ || i->Ain.Sse32FLo.op == Asse_RSQRTF
+ || i->Ain.Sse32FLo.op == Asse_SQRTF;
+ addHRegUse(u, HRmRead, i->Ain.Sse32FLo.src);
+ addHRegUse(u, unary ? HRmWrite : HRmModify,
+ i->Ain.Sse32FLo.dst);
+ return;
//.. case Xin_Sse64Fx2:
//.. vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
//.. unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
i->Ain.SseReRg.dst);
}
return;
-//.. case Xin_SseCMov:
-//.. addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
-//.. addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
-//.. return;
+ case Ain_SseCMov:
+ addHRegUse(u, HRmRead, i->Ain.SseCMov.src);
+ addHRegUse(u, HRmModify, i->Ain.SseCMov.dst);
+ return;
//.. case Xin_SseShuf:
//.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src);
//.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
mapReg(m, &i->Ain.SseSF2SI.src);
mapReg(m, &i->Ain.SseSF2SI.dst);
return;
+ case Ain_SseSDSS:
+ mapReg(m, &i->Ain.SseSDSS.src);
+ mapReg(m, &i->Ain.SseSDSS.dst);
+ return;
//.. case Xin_SseConst:
//.. mapReg(m, &i->Xin.SseConst.dst);
//.. return;
mapReg(m, &i->Ain.SseLdzLO.reg);
mapRegs_AMD64AMode(m, i->Ain.SseLdzLO.addr);
break;
-//.. case Xin_Sse32Fx4:
-//.. mapReg(m, &i->Xin.Sse32Fx4.src);
-//.. mapReg(m, &i->Xin.Sse32Fx4.dst);
-//.. return;
-//.. case Xin_Sse32FLo:
-//.. mapReg(m, &i->Xin.Sse32FLo.src);
-//.. mapReg(m, &i->Xin.Sse32FLo.dst);
-//.. return;
+ case Ain_Sse32Fx4:
+ mapReg(m, &i->Ain.Sse32Fx4.src);
+ mapReg(m, &i->Ain.Sse32Fx4.dst);
+ return;
+ case Ain_Sse32FLo:
+ mapReg(m, &i->Ain.Sse32FLo.src);
+ mapReg(m, &i->Ain.Sse32FLo.dst);
+ return;
//.. case Xin_Sse64Fx2:
//.. mapReg(m, &i->Xin.Sse64Fx2.src);
//.. mapReg(m, &i->Xin.Sse64Fx2.dst);
mapReg(m, &i->Ain.SseReRg.src);
mapReg(m, &i->Ain.SseReRg.dst);
return;
-//.. case Xin_SseCMov:
-//.. mapReg(m, &i->Xin.SseCMov.src);
-//.. mapReg(m, &i->Xin.SseCMov.dst);
-//.. return;
+ case Ain_SseCMov:
+ mapReg(m, &i->Ain.SseCMov.src);
+ mapReg(m, &i->Ain.SseCMov.dst);
+ return;
//.. case Xin_SseShuf:
//.. mapReg(m, &i->Xin.SseShuf.src);
//.. mapReg(m, &i->Xin.SseShuf.dst);
vreg2ireg(i->Ain.SseSF2SI.src) );
goto done;
+ case Ain_SseSDSS:
+ /* cvtsd2ss/cvtss2sd %src, %dst */
+ *p++ = i->Ain.SseSDSS.from64 ? 0xF2 : 0xF3;
+ *p++ = clearWBit(
+ rexAMode_R( vreg2ireg(i->Ain.SseSDSS.dst),
+ vreg2ireg(i->Ain.SseSDSS.src) ));
+ *p++ = 0x0F;
+ *p++ = 0x5A;
+ p = doAMode_R( p, vreg2ireg(i->Ain.SseSDSS.dst),
+ vreg2ireg(i->Ain.SseSDSS.src) );
+ goto done;
+
//..
//.. case Xin_FpCmp:
//.. /* gcmp %fL, %fR, %dst
*p++ = 0xF2;
} else
if (i->Ain.SseLdSt.sz == 4) {
- goto bad; /* awaiting test case */
*p++ = 0xF3;
} else
if (i->Ain.SseLdSt.sz != 16) {
i->Ain.SseLdzLO.addr);
goto done;
-//.. case Xin_Sse32Fx4:
-//.. xtra = 0;
-//.. *p++ = 0x0F;
-//.. switch (i->Xin.Sse32Fx4.op) {
-//.. case Xsse_ADDF: *p++ = 0x58; break;
-//.. case Xsse_DIVF: *p++ = 0x5E; break;
-//.. case Xsse_MAXF: *p++ = 0x5F; break;
-//.. case Xsse_MINF: *p++ = 0x5D; break;
-//.. case Xsse_MULF: *p++ = 0x59; break;
-//.. case Xsse_RCPF: *p++ = 0x53; break;
-//.. case Xsse_RSQRTF: *p++ = 0x52; break;
-//.. case Xsse_SQRTF: *p++ = 0x51; break;
-//.. case Xsse_SUBF: *p++ = 0x5C; break;
-//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
-//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
-//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
-//.. default: goto bad;
-//.. }
-//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
-//.. fake(vregNo(i->Xin.Sse32Fx4.src)) );
-//.. if (xtra & 0x100)
-//.. *p++ = (UChar)(xtra & 0xFF);
-//.. goto done;
-//..
+ case Ain_Sse32Fx4:
+ xtra = 0;
+ *p++ = clearWBit(
+ rexAMode_R( vreg2ireg(i->Ain.Sse32Fx4.dst),
+ vreg2ireg(i->Ain.Sse32Fx4.src) ));
+ *p++ = 0x0F;
+ switch (i->Ain.Sse32Fx4.op) {
+ //case Asse_ADDF: *p++ = 0x58; break;
+ //case Asse_DIVF: *p++ = 0x5E; break;
+ //case Asse_MAXF: *p++ = 0x5F; break;
+ //case Asse_MINF: *p++ = 0x5D; break;
+ //case Asse_MULF: *p++ = 0x59; break;
+ //case Asse_RCPF: *p++ = 0x53; break;
+ //case Asse_RSQRTF: *p++ = 0x52; break;
+ //case Asse_SQRTF: *p++ = 0x51; break;
+ //case Asse_SUBF: *p++ = 0x5C; break;
+ case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+ //case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+ //case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+ default: goto bad;
+ }
+ p = doAMode_R(p, vreg2ireg(i->Ain.Sse32Fx4.dst),
+ vreg2ireg(i->Ain.Sse32Fx4.src) );
+ if (xtra & 0x100)
+ *p++ = (UChar)(xtra & 0xFF);
+ goto done;
+
//.. case Xin_Sse64Fx2:
//.. xtra = 0;
//.. *p++ = 0x66;
//.. if (xtra & 0x100)
//.. *p++ = (UChar)(xtra & 0xFF);
//.. goto done;
-//..
-//.. case Xin_Sse32FLo:
-//.. xtra = 0;
-//.. *p++ = 0xF3;
-//.. *p++ = 0x0F;
-//.. switch (i->Xin.Sse32FLo.op) {
-//.. case Xsse_ADDF: *p++ = 0x58; break;
+
+ case Ain_Sse32FLo:
+ xtra = 0;
+ *p++ = 0xF3;
+ *p++ = clearWBit(
+ rexAMode_R( vreg2ireg(i->Ain.Sse32FLo.dst),
+ vreg2ireg(i->Ain.Sse32FLo.src) ));
+ *p++ = 0x0F;
+ switch (i->Ain.Sse32FLo.op) {
+ case Asse_ADDF: *p++ = 0x58; break;
//.. case Xsse_DIVF: *p++ = 0x5E; break;
//.. case Xsse_MAXF: *p++ = 0x5F; break;
//.. case Xsse_MINF: *p++ = 0x5D; break;
-//.. case Xsse_MULF: *p++ = 0x59; break;
+ case Asse_MULF: *p++ = 0x59; break;
//.. case Xsse_RCPF: *p++ = 0x53; break;
//.. case Xsse_RSQRTF: *p++ = 0x52; break;
//.. case Xsse_SQRTF: *p++ = 0x51; break;
-//.. case Xsse_SUBF: *p++ = 0x5C; break;
+ case Asse_SUBF: *p++ = 0x5C; break;
//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
-//.. default: goto bad;
-//.. }
-//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
-//.. fake(vregNo(i->Xin.Sse32FLo.src)) );
-//.. if (xtra & 0x100)
-//.. *p++ = (UChar)(xtra & 0xFF);
-//.. goto done;
+ default: goto bad;
+ }
+ p = doAMode_R(p, vreg2ireg(i->Ain.Sse32FLo.dst),
+ vreg2ireg(i->Ain.Sse32FLo.src) );
+ if (xtra & 0x100)
+ *p++ = (UChar)(xtra & 0xFF);
+ goto done;
case Ain_Sse64FLo:
xtra = 0;
case Asse_SQRTF: *p++ = 0x51; break;
case Asse_SUBF: *p++ = 0x5C; break;
//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
-//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+ case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
default: goto bad;
}
switch (i->Ain.SseReRg.op) {
case Asse_MOV: /*movups*/ XX(rex); XX(0x0F); XX(0x10); break;
-//.. case Xsse_OR: XX(rex); XX(0x0F); XX(0x56); break;
+ case Asse_OR: XX(rex); XX(0x0F); XX(0x56); break;
case Asse_XOR: XX(rex); XX(0x0F); XX(0x57); break;
case Asse_AND: XX(rex); XX(0x0F); XX(0x54); break;
//.. case Xsse_PACKSSD: XX(0x66); XX(rex); XX(0x0F); XX(0x6B); break;
# undef XX
goto done;
-//.. case Xin_SseCMov:
-//.. /* jmp fwds if !condition */
-//.. *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
-//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
-//.. ptmp = p;
-//..
-//.. /* movaps %src, %dst */
-//.. *p++ = 0x0F;
-//.. *p++ = 0x28;
-//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
-//.. fake(vregNo(i->Xin.SseCMov.src)) );
-//..
-//.. /* Fill in the jump offset. */
-//.. *(ptmp-1) = p - ptmp;
-//.. goto done;
-//..
+ case Ain_SseCMov:
+ /* jmp fwds if !condition */
+ *p++ = 0x70 + (i->Ain.SseCMov.cond ^ 1);
+ *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
+ ptmp = p;
+
+ /* movaps %src, %dst */
+ *p++ = clearWBit(
+ rexAMode_R( vreg2ireg(i->Ain.SseCMov.dst),
+ vreg2ireg(i->Ain.SseCMov.src) ));
+ *p++ = 0x0F;
+ *p++ = 0x28;
+ p = doAMode_R(p, vreg2ireg(i->Ain.SseCMov.dst),
+ vreg2ireg(i->Ain.SseCMov.src) );
+
+ /* Fill in the jump offset. */
+ *(ptmp-1) = p - ptmp;
+ goto done;
+
//.. case Xin_SseShuf:
//.. *p++ = 0x66;
//.. *p++ = 0x0F;
static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
static HReg iselDblExpr ( ISelEnv* env, IRExpr* e );
-//static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
-//static HReg iselFltExpr ( ISelEnv* env, IRExpr* e );
+static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
+static HReg iselFltExpr ( ISelEnv* env, IRExpr* e );
static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
static HReg iselVecExpr ( ISelEnv* env, IRExpr* e );
}
-//.. /* Given a guest-state array descriptor, an index expression and a
-//.. bias, generate an X86AMode holding the relevant guest state
-//.. offset. */
-//..
-//.. static
-//.. X86AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr,
-//.. IRExpr* off, Int bias )
-//.. {
-//.. HReg tmp, roff;
-//.. Int elemSz = sizeofIRType(descr->elemTy);
-//.. Int nElems = descr->nElems;
-//..
-//.. /* throw out any cases not generated by an x86 front end. In
-//.. theory there might be a day where we need to handle them -- if
-//.. we ever run non-x86-guest on x86 host. */
-//..
-//.. if (nElems != 8 || (elemSz != 1 && elemSz != 8))
-//.. vpanic("genGuestArrayOffset(x86 host)");
-//..
-//.. /* Compute off into a reg, %off. Then return:
-//..
-//.. movl %off, %tmp
-//.. addl $bias, %tmp (if bias != 0)
-//.. andl %tmp, 7
-//.. ... base(%ebp, %tmp, shift) ...
-//.. */
-//.. tmp = newVRegI(env);
-//.. roff = iselIntExpr_R(env, off);
-//.. addInstr(env, mk_iMOVsd_RR(roff, tmp));
-//.. if (bias != 0) {
-//.. addInstr(env,
-//.. X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp));
-//.. }
-//.. addInstr(env,
-//.. X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(7), tmp));
-//.. vassert(elemSz == 1 || elemSz == 8);
-//.. return
-//.. X86AMode_IRRS( descr->base, hregX86_EBP(), tmp,
-//.. elemSz==8 ? 3 : 0);
-//.. }
-//..
-//..
+/* Given a guest-state array descriptor, an index expression and a
+ bias, generate an AMD64AMode holding the relevant guest state
+ offset. */
+
+static
+AMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr,
+ IRExpr* off, Int bias )
+{
+ HReg tmp, roff;
+ Int elemSz = sizeofIRType(descr->elemTy);
+ Int nElems = descr->nElems;
+
+ /* Throw out any cases not generated by an amd64 front end. In
+ theory there might be a day where we need to handle them -- if
+ we ever run non-amd64-guest on amd64 host. */
+
+ if (nElems != 8 || (elemSz != 1 && elemSz != 8))
+ vpanic("genGuestArrayOffset(amd64 host)");
+
+ /* Compute off into a reg, %off. Then return:
+
+ movq %off, %tmp
+ addq $bias, %tmp (if bias != 0)
+ andq %tmp, 7
+ ... base(%rbp, %tmp, shift) ...
+ */
+ tmp = newVRegI(env);
+ roff = iselIntExpr_R(env, off);
+ addInstr(env, mk_iMOVsd_RR(roff, tmp));
+ if (bias != 0) {
+ /* Make sure the bias is sane, in the sense that there are
+ no significant bits above bit 30 in it. */
+ vassert(-10000 < bias && bias < 10000);
+ addInstr(env,
+ AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(bias), tmp));
+ }
+ addInstr(env,
+ AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(7), tmp));
+ vassert(elemSz == 1 || elemSz == 8);
+ return
+ AMD64AMode_IRRS( descr->base, hregAMD64_RBP(), tmp,
+ elemSz==8 ? 3 : 0);
+}
+
/* Set the SSE unit's rounding mode to default (%mxcsr = 0x1F80) */
static
//.. addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
//.. add_to_esp(env, 4);
//.. }
-//..
-//..
-//.. /* Generate !src into a new vector register, and be sure that the code
-//.. is SSE1 compatible. Amazing that Intel doesn't offer a less crappy
-//.. way to do this.
-//.. */
-//.. static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
-//.. {
-//.. HReg dst = newVRegV(env);
-//.. /* Set dst to zero. Not strictly necessary, but the idea of doing
-//.. a FP comparison on whatever junk happens to be floating around
-//.. in it is just too scary. */
-//.. addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
-//.. /* And now make it all 1s ... */
-//.. addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
-//.. /* Finally, xor 'src' into it. */
-//.. addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
-//.. return dst;
-//.. }
-//..
-//..
+
+
+/* Generate !src into a new vector register, and be sure that the code
+ is SSE1 compatible. Amazing that Intel doesn't offer a less crappy
+ way to do this.
+*/
+static HReg do_sse_NotV128 ( ISelEnv* env, HReg src )
+{
+ HReg dst = newVRegV(env);
+ /* Set dst to zero. Not strictly necessary, but the idea of doing
+ a FP comparison on whatever junk happens to be floating around
+ in it is just too scary. */
+ addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst));
+ /* And now make it all 1s ... */
+ addInstr(env, AMD64Instr_Sse32Fx4(Asse_CMPEQF, dst, dst));
+ /* Finally, xor 'src' into it. */
+ addInstr(env, AMD64Instr_SseReRg(Asse_XOR, src, dst));
+ return dst;
+}
+
+
//.. /* Round an x87 FPU value to 53-bit-mantissa precision, to be used
//.. after most non-simple FPU operations (simple = +, -, *, / and
//.. sqrt).
break;
}
-//.. case Iex_GetI: {
-//.. X86AMode* am
-//.. = genGuestArrayOffset(
-//.. env, e->Iex.GetI.descr,
-//.. e->Iex.GetI.ix, e->Iex.GetI.bias );
-//.. HReg dst = newVRegI(env);
-//.. if (ty == Ity_I8) {
-//.. addInstr(env, X86Instr_LoadEX( 1, False, am, dst ));
-//.. return dst;
-//.. }
-//.. break;
-//.. }
+ case Iex_GetI: {
+ AMD64AMode* am
+ = genGuestArrayOffset(
+ env, e->Iex.GetI.descr,
+ e->Iex.GetI.ix, e->Iex.GetI.bias );
+ HReg dst = newVRegI(env);
+ if (ty == Ity_I8) {
+ addInstr(env, AMD64Instr_LoadEX( 1, False, am, dst ));
+ return dst;
+ }
+ break;
+ }
/* --------- CCALL --------- */
case Iex_CCall: {
}
-//.. /*---------------------------------------------------------*/
-//.. /*--- ISEL: Floating point expressions (32 bit) ---*/
-//.. /*---------------------------------------------------------*/
-//..
-//.. /* Nothing interesting here; really just wrappers for
-//.. 64-bit stuff. */
-//..
-//.. static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
-//.. {
-//.. HReg r = iselFltExpr_wrk( env, e );
-//.. # if 0
-//.. vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
-//.. # endif
-//.. vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
-//.. vassert(hregIsVirtual(r));
-//.. return r;
-//.. }
-//..
-//.. /* DO NOT CALL THIS DIRECTLY */
-//.. static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
-//.. {
-//.. IRType ty = typeOfIRExpr(env->type_env,e);
-//.. vassert(ty == Ity_F32);
-//..
+/*---------------------------------------------------------*/
+/*--- ISEL: Floating point expressions (32 bit) ---*/
+/*---------------------------------------------------------*/
+
+/* Nothing interesting here; really just wrappers for
+ 64-bit stuff. */
+
+static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
+{
+ HReg r = iselFltExpr_wrk( env, e );
+# if 0
+ vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+# endif
+ vassert(hregClass(r) == HRcVec128);
+ vassert(hregIsVirtual(r));
+ return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
+{
+ IRType ty = typeOfIRExpr(env->type_env,e);
+ vassert(ty == Ity_F32);
+
//.. if (e->tag == Iex_Tmp) {
//.. return lookupIRTemp(env, e->Iex.Tmp.tmp);
//.. }
//.. addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
//.. return res;
//.. }
-//..
-//.. if (e->tag == Iex_Binop
-//.. && e->Iex.Binop.op == Iop_F64toF32) {
-//.. /* Although the result is still held in a standard FPU register,
-//.. we need to round it to reflect the loss of accuracy/range
-//.. entailed in casting it to a 32-bit float. */
-//.. HReg dst = newVRegF(env);
-//.. HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
-//.. set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
-//.. addInstr(env, X86Instr_Fp64to32(src,dst));
-//.. set_FPU_rounding_default( env );
-//.. return dst;
-//.. }
-//..
+
+ if (e->tag == Iex_Binop
+ && e->Iex.Binop.op == Iop_F64toF32) {
+ /* Although the result is still held in a standard SSE register,
+ we need to round it to reflect the loss of accuracy/range
+ entailed in casting it to a 32-bit float. */
+ HReg dst = newVRegV(env);
+ HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+ set_SSE_rounding_mode( env, e->Iex.Binop.arg1 );
+ addInstr(env, AMD64Instr_SseSDSS(True/*D->S*/,src,dst));
+ set_SSE_rounding_default( env );
+ return dst;
+ }
+
//.. if (e->tag == Iex_Get) {
//.. X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
//.. hregX86_EBP() );
//.. add_to_esp(env, 4);
//.. return dst;
//.. }
-//..
-//.. ppIRExpr(e);
-//.. vpanic("iselFltExpr_wrk");
-//.. }
+
+ ppIRExpr(e);
+ vpanic("iselFltExpr_wrk");
+}
/*---------------------------------------------------------*/
return lookupIRTemp(env, e->Iex.Tmp.tmp);
}
-//.. if (e->tag == Iex_Const) {
-//.. union { UInt u32x2[2]; ULong u64; Double f64; } u;
-//.. HReg freg = newVRegF(env);
-//.. vassert(sizeof(u) == 8);
-//.. vassert(sizeof(u.u64) == 8);
-//.. vassert(sizeof(u.f64) == 8);
-//.. vassert(sizeof(u.u32x2) == 8);
-//..
-//.. if (e->Iex.Const.con->tag == Ico_F64) {
-//.. u.f64 = e->Iex.Const.con->Ico.F64;
-//.. }
-//.. else if (e->Iex.Const.con->tag == Ico_F64i) {
-//.. u.u64 = e->Iex.Const.con->Ico.F64i;
-//.. }
-//.. else
-//.. vpanic("iselDblExpr(x86): const");
-//..
-//.. addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[1])));
-//.. addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[0])));
-//.. addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg,
-//.. X86AMode_IR(0, hregX86_ESP())));
-//.. add_to_esp(env, 8);
-//.. return freg;
-//.. }
+ if (e->tag == Iex_Const) {
+ union { ULong u64; Double f64; } u;
+ HReg res = newVRegV(env);
+ HReg tmp = newVRegI(env);
+ vassert(sizeof(u) == 8);
+ vassert(sizeof(u.u64) == 8);
+ vassert(sizeof(u.f64) == 8);
+
+ if (e->Iex.Const.con->tag == Ico_F64) {
+ u.f64 = e->Iex.Const.con->Ico.F64;
+ }
+ else if (e->Iex.Const.con->tag == Ico_F64i) {
+ u.u64 = e->Iex.Const.con->Ico.F64i;
+ }
+ else
+ vpanic("iselDblExpr(amd64): const");
+
+ addInstr(env, AMD64Instr_Imm64(u.u64, tmp));
+ addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(tmp)));
+ addInstr(env, AMD64Instr_SseLdSt(
+ True/*load*/, 8, res,
+ AMD64AMode_IR(0, hregAMD64_RSP())
+ ));
+ add_to_rsp(env, 8);
+ return res;
+ }
if (e->tag == Iex_LDle) {
AMD64AMode* am;
return res;
}
-//.. if (e->tag == Iex_GetI) {
-//.. X86AMode* am
-//.. = genGuestArrayOffset(
-//.. env, e->Iex.GetI.descr,
-//.. e->Iex.GetI.ix, e->Iex.GetI.bias );
-//.. HReg res = newVRegF(env);
-//.. addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
-//.. return res;
-//.. }
-//..
+ if (e->tag == Iex_GetI) {
+ AMD64AMode* am
+ = genGuestArrayOffset(
+ env, e->Iex.GetI.descr,
+ e->Iex.GetI.ix, e->Iex.GetI.bias );
+ HReg res = newVRegV(env);
+ addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
+ return res;
+ }
+
//.. if (e->tag == Iex_Binop) {
//.. X86FpOp fpop = Xfp_INVALID;
//.. switch (e->Iex.Binop.op) {
return dst;
}
+ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_NegF64) {
+ /* Sigh ... very rough code. Could do much better. */
+ HReg r1 = newVRegI(env);
+ HReg dst = newVRegV(env);
+ HReg tv = newVRegV(env);
+ HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+ AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
+ addInstr(env, mk_vMOVsd_RR(src,dst));
+ addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
+ addInstr(env, AMD64Instr_Imm64( 1ULL<<63, r1 ));
+ addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1)));
+ addInstr(env, AMD64Instr_SseLdSt(True, 16, tv, rsp0));
+ addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tv, dst));
+ add_to_rsp(env, 16);
+ return dst;
+ }
+
//.. if (e->tag == Iex_Unop) {
//.. X86FpOp fpop = Xfp_INVALID;
//.. switch (e->Iex.Unop.op) {
//.. break;
//.. }
//.. }
-//..
-//.. /* --------- MULTIPLEX --------- */
-//.. if (e->tag == Iex_Mux0X) {
-//.. if (ty == Ity_F64
-//.. && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
-//.. HReg r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
-//.. HReg rX = iselDblExpr(env, e->Iex.Mux0X.exprX);
-//.. HReg r0 = iselDblExpr(env, e->Iex.Mux0X.expr0);
-//.. HReg dst = newVRegF(env);
-//.. addInstr(env, X86Instr_FpUnary(Xfp_MOV,rX,dst));
-//.. addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
-//.. addInstr(env, X86Instr_FpCMov(Xcc_Z,r0,dst));
-//.. return dst;
-//.. }
-//.. }
+
+ /* --------- MULTIPLEX --------- */
+ if (e->tag == Iex_Mux0X) {
+ HReg r8, rX, r0, dst;
+ vassert(ty == Ity_F64);
+ vassert(typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8);
+ r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+ rX = iselDblExpr(env, e->Iex.Mux0X.exprX);
+ r0 = iselDblExpr(env, e->Iex.Mux0X.expr0);
+ dst = newVRegV(env);
+ addInstr(env, mk_vMOVsd_RR(rX,dst));
+ addInstr(env, AMD64Instr_Test64(AMD64RI_Imm(0xFF), AMD64RM_Reg(r8)));
+ addInstr(env, AMD64Instr_SseCMov(Acc_Z,r0,dst));
+ return dst;
+ }
ppIRExpr(e);
vpanic("iselDblExpr_wrk");
if (e->tag == Iex_Const) {
HReg dst = newVRegV(env);
vassert(e->Iex.Const.con->tag == Ico_V128);
- if (e->Iex.Const.con->Ico.V128 == 0) {
+ if (e->Iex.Const.con->Ico.V128 == 0x0000) {
addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst));
return dst;
+ } else
+ if (e->Iex.Const.con->Ico.V128 == 0x00FF) {
+ AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
+ /* Both of these literals are sign-extended to 64 bits. */
+ addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
+ addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0xFFFFFFFF)));
+ addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, rsp0 ));
+ add_to_rsp(env, 16);
+ return dst;
} else {
goto vec_fail;
-#if 0
- addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
- return dst;
-#endif
+# if 0
+ addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
+ return dst;
+# endif
}
}
if (e->tag == Iex_Unop) {
switch (e->Iex.Unop.op) {
-//.. case Iop_Not128: {
-//.. HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
-//.. return do_sse_Not128(env, arg);
-//.. }
-//..
+ case Iop_NotV128: {
+ HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+ return do_sse_NotV128(env, arg);
+ }
+
//.. case Iop_CmpNEZ64x2: {
//.. /* We can use SSE2 instructions for this. */
//.. /* Ideally, we want to do a 64Ix2 comparison against zero of
return dst;
}
-//.. case Iop_32Uto128: {
-//.. HReg dst = newVRegV(env);
-//.. X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
-//.. X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg);
-//.. addInstr(env, X86Instr_Push(rmi));
-//.. addInstr(env, X86Instr_SseLdzLO(4, dst, esp0));
-//.. add_to_esp(env, 4);
-//.. return dst;
-//.. }
+ case Iop_32UtoV128: {
+ HReg dst = newVRegV(env);
+ AMD64AMode* rsp_m32 = AMD64AMode_IR(-32, hregAMD64_RSP());
+ AMD64RI* ri = iselIntExpr_RI(env, e->Iex.Unop.arg);
+ addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, ri, rsp_m32));
+ addInstr(env, AMD64Instr_SseLdzLO(4, dst, rsp_m32));
+ return dst;
+ }
case Iop_64UtoV128: {
HReg dst = newVRegV(env);
//.. addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
//.. return dst;
//.. }
-//..
+
//.. case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
//.. case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
//.. case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
-//.. case Iop_Add32F0x4: op = Xsse_ADDF; goto do_32F0x4;
+ case Iop_Add32F0x4: op = Asse_ADDF; goto do_32F0x4;
//.. case Iop_Div32F0x4: op = Xsse_DIVF; goto do_32F0x4;
//.. case Iop_Max32F0x4: op = Xsse_MAXF; goto do_32F0x4;
//.. case Iop_Min32F0x4: op = Xsse_MINF; goto do_32F0x4;
-//.. case Iop_Mul32F0x4: op = Xsse_MULF; goto do_32F0x4;
-//.. case Iop_Sub32F0x4: op = Xsse_SUBF; goto do_32F0x4;
-//.. do_32F0x4: {
-//.. HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
-//.. HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
-//.. HReg dst = newVRegV(env);
-//.. addInstr(env, mk_vMOVsd_RR(argL, dst));
-//.. addInstr(env, X86Instr_Sse32FLo(op, argR, dst));
-//.. return dst;
-//.. }
-//..
+ case Iop_Mul32F0x4: op = Asse_MULF; goto do_32F0x4;
+ case Iop_Sub32F0x4: op = Asse_SUBF; goto do_32F0x4;
+ do_32F0x4: {
+ HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+ HReg dst = newVRegV(env);
+ addInstr(env, mk_vMOVsd_RR(argL, dst));
+ addInstr(env, AMD64Instr_Sse32FLo(op, argR, dst));
+ return dst;
+ }
+
//.. case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
-//.. case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
+ case Iop_CmpLT64F0x2: op = Asse_CMPLTF; goto do_64F0x2;
//.. case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
case Iop_Add64F0x2: op = Asse_ADDF; goto do_64F0x2;
case Iop_Div64F0x2: op = Asse_DIVF; goto do_64F0x2;
//.. op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
//..
case Iop_AndV128: op = Asse_AND; goto do_SseReRg;
-//.. case Iop_Or128: op = Xsse_OR; goto do_SseReRg;
+ case Iop_OrV128: op = Asse_OR; goto do_SseReRg;
case Iop_XorV128: op = Asse_XOR; goto do_SseReRg;
//.. case Iop_Add8x16: op = Xsse_ADD8; goto do_SseReRg;
//.. case Iop_Add16x8: op = Xsse_ADD16; goto do_SseReRg;
r,am));
return;
}
-//.. if (tyd == Ity_F64) {
-//.. HReg r = iselDblExpr(env, stmt->Ist.STle.data);
-//.. addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
-//.. return;
-//.. }
+ if (tyd == Ity_F64) {
+ HReg r = iselDblExpr(env, stmt->Ist.STle.data);
+ addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, r, am));
+ return;
+ }
//.. if (tyd == Ity_F32) {
//.. HReg r = iselFltExpr(env, stmt->Ist.STle.data);
//.. addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, am));
return;
}
-//.. if (ty == Ity_F32) {
-//.. HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
-//.. X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
-//.. set_FPU_rounding_default(env); /* paranoia */
-//.. addInstr(env, X86Instr_FpLdSt( False/*store*/, 4, f32, am ));
-//.. return;
-//.. }
+ if (ty == Ity_F32) {
+ HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
+ AMD64AMode* am = AMD64AMode_IR(stmt->Ist.Put.offset, hregAMD64_RBP());
+ set_SSE_rounding_default(env); /* paranoia */
+ addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 4, f32, am ));
+ return;
+ }
if (ty == Ity_F64) {
HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
AMD64AMode* am = AMD64AMode_IR( stmt->Ist.Put.offset,
break;
}
-//.. /* --------- Indexed PUT --------- */
-//.. case Ist_PutI: {
-//.. X86AMode* am
-//.. = genGuestArrayOffset(
-//.. env, stmt->Ist.PutI.descr,
-//.. stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
-//..
-//.. IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
-//.. if (ty == Ity_F64) {
-//.. HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
-//.. addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
-//.. return;
-//.. }
-//.. if (ty == Ity_I8) {
-//.. HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
-//.. addInstr(env, X86Instr_Store( 1, r, am ));
-//.. return;
-//.. }
+ /* --------- Indexed PUT --------- */
+ case Ist_PutI: {
+ AMD64AMode* am
+ = genGuestArrayOffset(
+ env, stmt->Ist.PutI.descr,
+ stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+
+ IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+ if (ty == Ity_F64) {
+ HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
+ addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, val, am ));
+ return;
+ }
+ if (ty == Ity_I8) {
+ HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+ addInstr(env, AMD64Instr_Store( 1, r, am ));
+ return;
+ }
//.. if (ty == Ity_I64) {
//.. HReg rHi, rLo;
//.. X86AMode* am4 = advance4(am);
//.. addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
//.. return;
//.. }
-//.. break;
-//.. }
+ break;
+ }
/* --------- TMP --------- */
case Ist_Tmp: {