Make floating-point comparisons work, and fill in a bunch of other x86
FP -> IR cases.
git-svn-id: svn://svn.valgrind.org/vex/trunk@245 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host-x86/hdefs.c b/priv/host-x86/hdefs.c
index 070d4eb..dd47237 100644
--- a/priv/host-x86/hdefs.c
+++ b/priv/host-x86/hdefs.c
@@ -607,6 +607,15 @@
i->Xin.FpLdStCW.addr = addr;
return i;
}
+X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst )
+{
+ X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
+ i->tag = Xin_FpCmp;
+ i->Xin.FpCmp.srcL = srcL;
+ i->Xin.FpCmp.srcR = srcR;
+ i->Xin.FpCmp.dst = dst;
+ return i;
+}
void ppX86Instr ( X86Instr* i ) {
@@ -771,6 +780,14 @@
vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
ppX86AMode(i->Xin.FpLdStCW.addr);
return;
+ case Xin_FpCmp:
+ vex_printf("gcmp ");
+ ppHRegX86(i->Xin.FpCmp.srcL);
+ vex_printf(",");
+ ppHRegX86(i->Xin.FpCmp.srcR);
+ vex_printf(",");
+ ppHRegX86(i->Xin.FpCmp.dst);
+ break;
default:
vpanic("ppX86Instr");
}
@@ -890,6 +907,12 @@
case Xin_FpLdStCW:
addRegUsage_X86AMode(u, i->Xin.FpLdStCW.addr);
return;
+ case Xin_FpCmp:
+ addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
+ addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
+ addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
+ addHRegUse(u, HRmWrite, hregX86_EAX());
+ return;
default:
ppX86Instr(i);
vpanic("getRegUsage_X86Instr");
@@ -981,6 +1004,11 @@
case Xin_FpLdStCW:
mapRegs_X86AMode(m, i->Xin.FpLdStCW.addr);
return;
+ case Xin_FpCmp:
+ mapReg(m, &i->Xin.FpCmp.srcL);
+ mapReg(m, &i->Xin.FpCmp.srcR);
+ mapReg(m, &i->Xin.FpCmp.dst);
+ return;
default:
ppX86Instr(i);
vpanic("mapRegs_X86Instr");
@@ -1797,7 +1825,7 @@
--> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
*/
switch (i->Xin.FpLdStI.sz) {
- case 8: vassert(0); opc = 0xDF; subopc_imm = 5; break;
+ case 8: opc = 0xDF; subopc_imm = 5; break;
case 4: opc = 0xDB; subopc_imm = 0; break;
case 2: vassert(0); opc = 0xDF; subopc_imm = 0; break;
default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
@@ -1825,29 +1853,6 @@
}
break;
-#if 0
- case Xin_FpI64:
- if (i->Xin.FpI64.toInt) {
- vassert(0);
- } else {
- /* gi64tof64 %hi:%lo %fakeN
- --> ffree %st7; pushl hi ; pushl lo ; fildll 0(%esp) ;
- addl $8,%esp ; fstpl %st(N+1)
- */
- /* ffree %st(7) */
- p = do_ffree_st7(p);
- /* pushl %hi ; pushl %lo */
- *p++ = 0x50 + iregNo(i->Xin.FpI64.iregHi);
- *p++ = 0x50 + iregNo(i->Xin.FpI64.iregLo);
- /* fildll 0(%esp) */
- *p++ = 0xDF; *p++ = 0x6C; *p++ = 0x24; *p++ = 0x00;
- /* addl $8, %esp */
- *p++ = 0x83; *p++ = 0xC4; *p++ = 0x08;
- p = do_fstp_st(p, 1+fregNo(i->Xin.FpI64.freg));
- goto done;
- }
-#endif
-
case Xin_FpCMov:
/* jmp fwds if !condition */
*p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
@@ -1856,8 +1861,8 @@
/* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpCMov.src));
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpCMov.dst));
+ p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
+ p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
/* Fill in the jump offset. */
*(ptmp-1) = p - ptmp;
@@ -1872,6 +1877,27 @@
}
goto done;
+
+ case Xin_FpCmp:
+ /* gcmp %fL, %fR, %dst
+ -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
+ fnstsw %ax ; movl %eax, %dst
+ */
+ /* ffree %st7 */
+ p = do_ffree_st7(p);
+ /* fpush %fL */
+ p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
+ /* fucomp %(fR+1) */
+ *p++ = 0xDD;
+ *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
+ /* fnstsw %ax */
+ *p++ = 0xDF;
+ *p++ = 0xE0;
+ /* movl %eax, %dst */
+ *p++ = 0x89;
+ p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
+ goto done;
+
default:
goto bad;
}