Fix a large number of cases at both ends of the pipeline for x86
floating point, and some integer stuff. The FP to integer conversions
are somewhat misguided and need reworking.
git-svn-id: svn://svn.valgrind.org/vex/trunk@238 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest-x86/toIR.c b/priv/guest-x86/toIR.c
index ecb7e2b..aa0e858 100644
--- a/priv/guest-x86/toIR.c
+++ b/priv/guest-x86/toIR.c
@@ -3256,7 +3256,8 @@
if (dbl) {
put_ST_UNCHECKED(0, binop(op, get_ST(0), loadLE(Ity_F64,mkexpr(addr))));
} else {
- vassert(0);
+ put_ST_UNCHECKED(0, binop(op, get_ST(0),
+ unop(Iop_F32toF64,loadLE(Ity_F32,mkexpr(addr)))));
}
}
@@ -3281,7 +3282,7 @@
Int len;
UInt r_src, r_dst;
Char dis_buf[32];
- IRTemp t1;
+ IRTemp t1, t2;
/* On entry, delta points at the second byte of the insn (the modrm
byte).*/
@@ -3292,13 +3293,35 @@
if (first_opcode == 0xD8) {
if (modrm < 0xC0) {
- goto decode_fail;
+
+ /* 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 1: /* FMUL single-real */
+ fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
+ break;
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xD8\n");
+ goto decode_fail;
+ }
} else {
delta++;
switch (modrm) {
+
case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0 );
break;
+
+ case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
+ fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0 );
+ break;
+
default:
goto decode_fail;
}
@@ -3309,10 +3332,46 @@
else
if (first_opcode == 0xD9) {
if (modrm < 0xC0) {
- goto decode_fail;
+
+ /* 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 single-real */
+ DIP("fldF %s\n", dis_buf);
+ fp_push();
+ put_ST(0, unop(Iop_F32toF64,
+ IRExpr_LDle(Ity_F32, mkexpr(addr))));
+ break;
+
+ case 3: /* FSTP single-real */
+ DIP("fstpS %s", dis_buf);
+ storeLE(mkexpr(addr), unop(Iop_F64toF32, get_ST(0)));
+ fp_pop();
+ break;
+
+ case 5:
+ vex_printf("vex x86->IR: ignoring fldcw\n");
+ break;
+
+ case 7:
+ vex_printf("vex x86->IR: ignoring fstcw\n");
+ storeLE(mkexpr(addr), mkU16(0x037F));
+ 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) {
+
case 0xC0 ... 0xC7: /* FLD %st(?) */
r_src = (UInt)modrm - 0xC0;
DIP("fld %%st(%d)\n", r_src);
@@ -3322,7 +3381,18 @@
put_ST(0, mkexpr(t1));
break;
- case 0xE8: /* FLD1 */
+ 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 0xE8: /* FLD1 */
DIP("fld1");
fp_push();
put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
@@ -3389,9 +3459,8 @@
put_ST_UNCHECKED(0,
binop(fop,
get_ST(0),
- unop(Iop_I64toF64,
- unop(Iop_32Sto64,
- loadLE(Ity_I32, mkexpr(addr))))));
+ unop(Iop_I32toF64,
+ loadLE(Ity_I32, mkexpr(addr)))));
break;
default:
@@ -3407,7 +3476,37 @@
/* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
else
if (first_opcode == 0xDB) {
- goto decode_fail;
+ 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: /* FILD m32int */
+ DIP("fildl %s\n", dis_buf);
+ fp_push();
+ put_ST(0, unop(Iop_I32toF64,
+ loadLE(Ity_I32, mkexpr(addr))));
+ break;
+
+ case 3: /* FISTP m32 */
+ DIP("fistpl %s", dis_buf);
+ storeLE(mkexpr(addr), unop(Iop_F64toI32,get_ST(0)));
+ fp_pop();
+ break;
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xDB\n");
+ goto decode_fail;
+ }
+
+ } else {
+ goto decode_fail;
+ }
}
/* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
@@ -3415,8 +3514,8 @@
if (first_opcode == 0xDC) {
if (modrm < 0xC0) {
- /* bits 5,4,3 are an opcode extension, and the modRM also
- specifies an address. */
+ /* 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;
@@ -3456,18 +3555,11 @@
put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
break;
-#if 0
case 2: /* FST double-real */
- IFDB( if (dis) printf("\tfstD\t%s\n",t_addr); )
- if (!fp_is_empty_tag(fp_get_tag_ST(0))) {
- vd_addr = fp_get_reg_ST(0);
- } else {
- vd_addr = NAN;
- fp_set_stack_underflow();
- }
- setDMem(a_addr,vd_addr);
+ DIP("fstD %s", dis_buf);
+ storeLE(mkexpr(addr), get_ST(0));
break;
-#endif
+
case 3: /* FSTP double-real */
DIP("fstpD %s", dis_buf);
storeLE(mkexpr(addr), get_ST(0));
@@ -3506,7 +3598,41 @@
/* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
else
if (first_opcode == 0xDF) {
- goto decode_fail;
+
+ 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 3: /* FISTP m16 */
+ DIP("fistps %s", dis_buf);
+ storeLE(mkexpr(addr), unop(Iop_F64toI16,get_ST(0)));
+ fp_pop();
+ break;
+
+#if 0
+ case 5: /* FILD m64 */
+ DIP("fildll %s\n", dis_buf);
+ fp_push();
+ put_ST(0, unop(Iop_I64toF64,
+ loadLE(Ity_I64, mkexpr(addr))));
+ break;
+#endif
+
+ default:
+ vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+ vex_printf("first_opcode == 0xDF\n");
+ goto decode_fail;
+ }
+
+ } else {
+ goto decode_fail;
+ }
+
}
else
@@ -7079,9 +7205,9 @@
/* ------------------------ opl Ev, Gv ----------------- */
-//-- case 0x02: /* ADD Eb,Gb */
-//-- delta = dis_op2_E_G ( cb, sorb, False, ADD, True, 1, delta, "add" );
-//-- break;
+ case 0x02: /* ADD Eb,Gb */
+ delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, 1, delta, "add" );
+ break;
case 0x03: /* ADD Ev,Gv */
delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, sz, delta, "add" );
break;
@@ -8068,10 +8194,14 @@
DIP("j%s-32 0x%x\n", name_Condcode(opc - 0x80), d32);
break;
-//--
-//-- /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
-//--
-//-- case 0x31: /* RDTSC */
+
+ /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
+
+ case 0x31: /* RDTSC */
+ vex_printf("vex x86->IR: kludged rdtsc\n");
+ putIReg(4, R_EAX, mkU32(0));
+ putIReg(4, R_EDX, mkU32(0));
+
//-- t1 = newTemp(cb);
//-- t2 = newTemp(cb);
//-- t3 = newTemp(cb);
@@ -8092,8 +8222,8 @@
//-- uInstr1(cb, POP, 4, TempReg, t3);
//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_EAX);
//-- uInstr0(cb, CALLM_E, 0);
-//-- DIP("rdtsc\n");
-//-- break;
+ DIP("rdtsc\n");
+ break;
/* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
case 0x90: