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,