mips32: Fix the problem with the floating point compare instruction on mips32.
This patch is fixing the problem with emitting Iop_CmpF64.
Problem was introduced while running Valgrind for mips with v8 javascript engine.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2825 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_mips_toIR.c b/priv/guest_mips_toIR.c
index 94ec293..d95d583 100644
--- a/priv/guest_mips_toIR.c
+++ b/priv/guest_mips_toIR.c
@@ -1697,22 +1697,22 @@
static const HChar* showCondCode(UInt code) {
const HChar* ret;
switch (code) {
- case 0: ret = "F"; break;
- case 1: ret = "UN"; break;
- case 2: ret = "EQ"; break;
- case 3: ret = "UEQ"; break;
- case 4: ret = "OLT"; break;
- case 5: ret = "ULT"; break;
- case 6: ret = "OLE"; break;
- case 7: ret = "ULE"; break;
- case 8: ret = "SF"; break;
- case 9: ret = "NGLE"; break;
- case 10: ret = "SEQ"; break;
- case 11: ret = "NGL"; break;
- case 12: ret = "LT"; break;
- case 13: ret = "NGE"; break;
- case 14: ret = "LE"; break;
- case 15: ret = "NGT"; break;
+ case 0: ret = "f"; break;
+ case 1: ret = "un"; break;
+ case 2: ret = "eq"; break;
+ case 3: ret = "ueq"; break;
+ case 4: ret = "olt"; break;
+ case 5: ret = "ult"; break;
+ case 6: ret = "ole"; break;
+ case 7: ret = "ule"; break;
+ case 8: ret = "sf"; break;
+ case 9: ret = "ngle"; break;
+ case 10: ret = "seq"; break;
+ case 11: ret = "ngl"; break;
+ case 12: ret = "lt"; break;
+ case 13: ret = "nge"; break;
+ case 14: ret = "le"; break;
+ case 15: ret = "ngt"; break;
default: vpanic("showCondCode"); break;
}
return ret;
@@ -1733,7 +1733,7 @@
UInt fpc_cc = get_fpc_cc(cins);
switch (fmt) {
case 0x10: { /* C.cond.S */
- DIP("C.%s.S %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
+ DIP("c.%s.s %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
if (fp_mode64) {
t0 = newTemp(Ity_I32);
t1 = newTemp(Ity_I32);
@@ -1942,7 +1942,7 @@
break;
case 0x11: { /* C.cond.D */
- DIP("C.%s.D %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
+ DIP("c.%s.d %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
t0 = newTemp(Ity_I32);
t1 = newTemp(Ity_I32);
t2 = newTemp(Ity_I32);
diff --git a/priv/host_mips_defs.c b/priv/host_mips_defs.c
index e708434..2e34b99 100644
--- a/priv/host_mips_defs.c
+++ b/priv/host_mips_defs.c
@@ -802,8 +802,17 @@
case Mfp_CEILLD:
ret = "ceil.l.d";
break;
- case Mfp_CMP:
- ret = "C.cond.d";
+ case Mfp_CMP_UN:
+ ret = "c.un.d";
+ break;
+ case Mfp_CMP_EQ:
+ ret = "c.eq.d";
+ break;
+ case Mfp_CMP_LT:
+ ret = "c.lt.d";
+ break;
+ case Mfp_CMP_NGT:
+ ret = "c.ngt.d";
break;
default:
vex_printf("Unknown op: %d", op);
@@ -1503,8 +1512,7 @@
}
-MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR,
- UChar cond1)
+MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR)
{
MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
i->tag = Min_FpCompare;
@@ -1512,7 +1520,6 @@
i->Min.FpCompare.dst = dst;
i->Min.FpCompare.srcL = srcL;
i->Min.FpCompare.srcR = srcR;
- i->Min.FpCompare.cond1 = cond1;
return i;
}
@@ -1817,7 +1824,6 @@
ppHRegMIPS(i->Min.FpCompare.srcL, mode64);
vex_printf(",");
ppHRegMIPS(i->Min.FpCompare.srcR, mode64);
- vex_printf(" cond: %c", i->Min.FpCompare.cond1);
return;
case Min_FpMulAcc:
vex_printf("%s ", showMIPSFpOp(i->Min.FpMulAcc.op));
@@ -3983,19 +3989,35 @@
}
case Min_FpCompare: {
- UInt r_dst = iregNo(i->Min.FpCompare.dst, mode64);
+ UInt r_dst = iregNo(i->Min.FpCompare.dst, mode64);
UInt fr_srcL = dregNo(i->Min.FpCompare.srcL);
UInt fr_srcR = dregNo(i->Min.FpCompare.srcR);
+ UInt op;
switch (i->Min.FpConvert.op) {
- case Mfp_CMP:
- p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0,
- (i->Min.FpCompare.cond1 + 48));
- p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0);
+ case Mfp_CMP_UN:
+ op = 1;
break;
+ case Mfp_CMP_EQ:
+ op = 2;
+ break;
+ case Mfp_CMP_LT:
+ op = 12;
+ break;
+ case Mfp_CMP_NGT:
+ op = 15;
+ break;
default:
goto bad;
}
+ /* c.cond.d fr_srcL, fr_srcR
+ cfc1 r_dst, $31
+ srl r_dst, r_dst, 23
+ andi r_dst, r_dst, 1 */
+ p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0, op + 48);
+ p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0);
+ p = mkFormS(p, 0, r_dst, 0, r_dst, 23, 2);
+ p = mkFormI(p, 12, r_dst, r_dst, 1);
goto done;
}
diff --git a/priv/host_mips_defs.h b/priv/host_mips_defs.h
index dceb892..cc2b48f 100644
--- a/priv/host_mips_defs.h
+++ b/priv/host_mips_defs.h
@@ -366,8 +366,11 @@
Mfp_CVTSD, Mfp_CVTSW, Mfp_CVTWD,
Mfp_CVTWS, Mfp_CVTDL, Mfp_CVTSL, Mfp_CVTLS, Mfp_CVTLD, Mfp_TRULS, Mfp_TRULD,
Mfp_TRUWS, Mfp_TRUWD, Mfp_FLOORWS, Mfp_FLOORWD, Mfp_ROUNDWS, Mfp_ROUNDWD,
- Mfp_CVTDW, Mfp_CMP, Mfp_CEILWS, Mfp_CEILWD, Mfp_CEILLS, Mfp_CEILLD,
- Mfp_CVTDS, Mfp_ROUNDLD, Mfp_FLOORLD
+ Mfp_CVTDW, Mfp_CEILWS, Mfp_CEILWD, Mfp_CEILLS, Mfp_CEILLD, Mfp_CVTDS,
+ Mfp_ROUNDLD, Mfp_FLOORLD,
+
+ /* FP compare */
+ Mfp_CMP_UN, Mfp_CMP_EQ, Mfp_CMP_LT, Mfp_CMP_NGT
} MIPSFpOp;
@@ -664,7 +667,7 @@
HReg src2, HReg src3 );
extern MIPSInstr *MIPSInstr_FpConvert(MIPSFpOp op, HReg dst, HReg src);
extern MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL,
- HReg srcR, UChar cond1);
+ HReg srcR);
extern MIPSInstr *MIPSInstr_FpMulAcc(MIPSFpOp op, HReg dst, HReg srcML,
HReg srcMR, HReg srcAcc);
extern MIPSInstr *MIPSInstr_FpLdSt(Bool isLoad, UChar sz, HReg, MIPSAMode *);
diff --git a/priv/host_mips_isel.c b/priv/host_mips_isel.c
index 088b808..735386c 100644
--- a/priv/host_mips_isel.c
+++ b/priv/host_mips_isel.c
@@ -1123,29 +1123,24 @@
/* Create in dst, the IRCmpF64Result encoded result. */
/* chech for EQ */
- addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
- toUChar(2)));
- addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_ccMIPS, tmp,
- MIPSRH_Imm(False, 22)));
+ addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ, tmp, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccMIPS, tmp,
+ MIPSRH_Imm(False, 1)));
/* chech for UN */
- addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
- toUChar(1)));
- addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
- MIPSRH_Imm(False, 23)));
+ addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN, tmp, r_srcL, r_srcR));
addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
MIPSRH_Reg(tmp)));
/* chech for LT */
- addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
- toUChar(12)));
- addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp,
- tmp, MIPSRH_Imm(False, 21)));
+ addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT, tmp, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp,
+ tmp, MIPSRH_Imm(False, 2)));
addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
MIPSRH_Reg(tmp)));
/* chech for GT */
- addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
- toUChar(15)));
- addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
- MIPSRH_Imm(False, 20)));
+ addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_NGT,
+ tmp, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, tmp,
+ MIPSRH_Imm(False, 3)));
addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,