]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Load/store doubles on MIPS are modeled through Ity_F64 rather than two Ity_F32.
authorPetar Jovanovic <mips32r2@gmail.com>
Tue, 4 Sep 2012 13:45:42 +0000 (13:45 +0000)
committerPetar Jovanovic <mips32r2@gmail.com>
Tue, 4 Sep 2012 13:45:42 +0000 (13:45 +0000)
This patch changes how the load/store doublewords are modeled on MIPS.
Previously, this was modeled through two Ity_F32s which caused test reports to
be different to expected.
This fixes memcheck/tests/fprw.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2511

VEX/priv/guest_mips_toIR.c
VEX/priv/host_mips_defs.c
VEX/priv/host_mips_isel.c

index 3c72619cdf0665f74d21a0a25e58a288a189e399..2e60ed7c30bba4f9f72f4f7c1f5aa9c037ddbae3 100644 (file)
@@ -2173,36 +2173,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
    case 0x35:
       /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
       LOAD_STORE_PATTERN;
-
-      t2 = newTemp(Ity_I32);
-      assign(t2, binop(Iop_Add32, getIReg(rs),
-                       mkU32(extend_s_16to32(imm + 4))));
-
-#if defined (_MIPSEL)
-      putFReg(ft, load(Ity_F32, mkexpr(t1)));
-      putFReg(ft + 1, load(Ity_F32, mkexpr(t2)));
-#elif defined (_MIPSEB)
-      putFReg(ft + 1, load(Ity_F32, mkexpr(t1)));
-      putFReg(ft, load(Ity_F32, mkexpr(t2)));
-#endif
+      putDReg(ft, load(Ity_F64, mkexpr(t1)));
       DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs);
       break;
 
    case 0x3D:
       /* Store Doubleword from Floating Point - SDC1 */
       LOAD_STORE_PATTERN;
-
-      t2 = newTemp(Ity_I32);
-      assign(t2, binop(Iop_Add32, getIReg(rs),
-                       mkU32(extend_s_16to32(imm + 4))));
-
-#if defined (_MIPSEL)
-      store(mkexpr(t1), getFReg(ft));
-      store(mkexpr(t2), getFReg(ft + 1));
-#elif defined (_MIPSEB)
-      store(mkexpr(t1), getFReg(ft + 1));
-      store(mkexpr(t2), getFReg(ft));
-#endif
+      store(mkexpr(t1), getDReg(ft));
       DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
       break;
 
@@ -2310,7 +2288,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
          store(mkexpr(t1), getFReg(fs));
 #endif
 
-         DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
+         DIP("sdxc1 f%d, %d(%d)", ft, imm, rs);
          break;
       }
       case 0x0F: {
index f2a1e82934069442dc6227ea508ef245bc23f8ef..86e8ee8f74ef025a50f33e48299fbf5f7a34ee4d 100644 (file)
@@ -860,7 +860,7 @@ MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am)
    MIPSAMode* ret;
    switch (am->tag) {
       case Mam_IR:
-         ret = MIPSAMode_IR(am->Mam.IR.index + 8, am->Mam.IR.base);
+         ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
          break;
       case Mam_RR:
          ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base);
@@ -1736,18 +1736,12 @@ void ppMIPSInstr(MIPSInstr * i, Bool mode64)
             }
          } else if (i->Min.FpLdSt.sz == 8) {
             if (i->Min.FpLdSt.isLoad) {
-               if (mode64)
-                  vex_printf("ldc1 ");
-               else
-                  vex_printf("lwc1 ");
+               vex_printf("ldc1 ");
                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
                vex_printf(",");
                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
             } else {
-               if (mode64)
-                  vex_printf("sdc1 ");
-               else
-                  vex_printf("swc1 ");
+               vex_printf("sdc1 ");
                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
                vex_printf(",");
                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
@@ -1952,16 +1946,9 @@ void getRegUsage_MIPSInstr(HRegUsage * u, MIPSInstr * i, Bool mode64)
             addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
             return;
          } else if (i->Min.FpLdSt.sz == 8) {
-            if (mode64) {
-               addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
-                              i->Min.FpLdSt.reg);
-               addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
-            } else {
-               addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
-                              i->Min.FpLdSt.reg);
-               addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
-               addRegUsage_MIPSAMode(u, nextMIPSAModeFloat(i->Min.FpLdSt.addr));
-            }
+            addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
+                           i->Min.FpLdSt.reg);
+            addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
             return;
          }
          break;
@@ -2107,14 +2094,8 @@ void mapRegs_MIPSInstr(HRegRemap * m, MIPSInstr * i, Bool mode64)
             mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
             return;
          } else if (i->Min.FpLdSt.sz == 8) {
-            if (mode64) {
-               mapReg(m, &i->Min.FpLdSt.reg);
-               mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
-            } else {
-               mapReg(m, &i->Min.FpLdSt.reg);
-               mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
-               mapRegs_MIPSAMode(m, nextMIPSAModeFloat(i->Min.FpLdSt.addr));
-            }
+            mapReg(m, &i->Min.FpLdSt.reg);
+            mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
             return;
          }
          break;
@@ -3515,39 +3496,15 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
             UInt f_reg = dregNo(i->Min.FpLdSt.reg);
             if (i->Min.FpLdSt.isLoad) {
                if (am_addr->tag == Mam_IR) {
-                  if (mode64) {
-                     p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64);
-                  } else {
-                     p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64);
-                     p = doAMode_IR(p, 0x31, f_reg + 1,
-                                   nextMIPSAModeFloat(am_addr), mode64);
-                  }
+                  p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64);
                } else if (am_addr->tag == Mam_RR) {
-                  if (mode64) {
-                     p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64);
-                  } else {
-                     p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64);
-                     p = doAMode_RR(p, 0x31, f_reg + 1,
-                                    nextMIPSAModeFloat(am_addr), mode64);
-                  }
+                  p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64);
                }
             } else {
                if (am_addr->tag == Mam_IR) {
-                  if (mode64) {
-                     p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64);
-                  } else {
-                     p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64);
-                     p = doAMode_IR(p, 0x39, f_reg + 1,
-                                    nextMIPSAModeFloat(am_addr), mode64);
-                  }
+                  p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64);
                } else if (am_addr->tag == Mam_RR) {
-                  if (mode64) {
-                     p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64);
-                  } else {
-                     p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64);
-                     p = doAMode_RR(p, 0x39, f_reg + 1,
-                                    nextMIPSAModeFloat(am_addr), mode64);
-                  }
+                  p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64);
                }
             }
          }
index 347a682fdfe8e6ecb9a1bf978d7f5b534ec2fba4..c0fa0280e3e91e13c66500f3bcff1c4201ef6f8c 100644 (file)
@@ -344,7 +344,7 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
 
    sub_from_sp(env, 16);   // Move SP down 16 bytes
    am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
-   am_addr1 = MIPSAMode_IR(8, StackPointer(mode64));
+   am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
 
    // store hi,lo as Ity_I32's
    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
@@ -445,15 +445,21 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
          vassert(argreg < MIPS_N_REGPARMS);
          vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
                  || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
-         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
+         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || mode64) {
             argiregs |= (1 << (argreg + 4));
             addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
                      args[i])));
          } else { // Ity_I64
-            vassert(mode64);
+            if (argreg & 1) {
+               argreg++;
+               argiregs |= (1 << (argreg + 4));
+            }
+            HReg rHi, rLo;
+            iselInt64Expr(&rHi, &rLo, env, args[i]);
             argiregs |= (1 << (argreg + 4));
-            addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
-                     args[i])));
+            addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
+            argiregs |= (1 << (argreg + 4));
+            addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
          }
          argreg++;
       }
@@ -474,11 +480,18 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
          vassert(argreg < MIPS_N_REGPARMS);
          vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
                  || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
-         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
+         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || mode64) {
             tmpregs[argreg] = iselWordExpr_R(env, args[i]);
          } else { // Ity_I64
-            vassert(mode64);
-            tmpregs[argreg] = iselWordExpr_R(env, args[i]);
+            if (argreg & 1)
+               argreg++;
+            if (argreg + 1 >= MIPS_N_REGPARMS)
+               vassert(0);  /* out of argregs */
+            HReg raHi, raLo;
+            iselInt64Expr(&raHi, &raLo, env, args[i]);
+            tmpregs[argreg] = raLo;
+            argreg++;
+            tmpregs[argreg] = raHi;             
          }
          argreg++;
       }
@@ -2249,10 +2262,10 @@ static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
             sub_from_sp(env, 16);   // Move SP down 16 bytes
             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
 
-            // store as I32                                 
+            // store as I64                                 
             addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
 
-            // load as Ity_F32
+            // load as Ity_F64
             addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
 
             add_to_sp(env, 16);  // Reset SP
@@ -2783,6 +2796,13 @@ static void iselStmt(ISelEnv * env, IRStmt * stmt)
             return;
          }
 
+         if (!mode64 && (tyd == Ity_F64)) {
+            HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
+                                           am_addr));
+            return;
+         }
+
          break;
       }
 
@@ -2893,8 +2913,14 @@ static void iselStmt(ISelEnv * env, IRStmt * stmt)
 
          retty = typeOfIRTemp(env->type_env, d->tmp);
          if (retty == Ity_I64 && !mode64) {
-            vex_printf
-                ("Dirty! Return 64 bits. Not implemented (yet!)\n");
+            HReg rHi = newVRegI(env);
+            HReg rLo = newVRegI(env);
+            HReg dstHi, dstLo;
+            addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64)));
+            addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64)));
+            lookupIRTemp64(&dstHi, &dstLo, env, d->tmp);
+            addInstr(env, mk_iMOVds_RR(dstHi, rHi));
+            addInstr(env, mk_iMOVds_RR(dstLo, rLo));
             return;
          }
          if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32