]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips: fix endian issues for LWL, LWR, LDR and LDL for mips64
authorPetar Jovanovic <mips32r2@gmail.com>
Fri, 19 Apr 2013 12:35:00 +0000 (12:35 +0000)
committerPetar Jovanovic <mips32r2@gmail.com>
Fri, 19 Apr 2013 12:35:00 +0000 (12:35 +0000)
This change:
- fixes endian issues for unaligned loads for MIPS64,
- (re)moves endian dependencies in guest-to-IR for Iop_ReinterpI32asF32
   and Iop_ReinterpI64asF64 to host-mips-isel,
- adds minor style changes in the area touched by the code.

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

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

index 9c368f4773cd7ff7fb0750fd0af9b740db82928c..62f67f1f987b5ea83545dd1ed6922869cc877b05 100644 (file)
@@ -72,6 +72,10 @@ static IRSB *irsb;
    disInstr_MIPS below. */
 static Bool mode64 = False;
 
+/* Define 1.0 in single and double precision. */
+#define ONE_SINGLE 0x3F800000
+#define ONE_DOUBLE 0x3FF0000000000000ULL
+
 /*------------------------------------------------------------*/
 /*---                  Debugging output                    ---*/
 /*------------------------------------------------------------*/
@@ -1163,13 +1167,8 @@ static IRExpr *getDReg(UInt dregNo)
       IRTemp t4 = newTemp(Ity_I32);
       IRTemp t5 = newTemp(Ity_I64);
 
-#if defined (_MIPSEL)
       assign(t0, getFReg(dregNo));
       assign(t1, getFReg(dregNo + 1));
-#elif defined (_MIPSEB)
-      assign(t0, getFReg(dregNo + 1));
-      assign(t1, getFReg(dregNo));
-#endif
 
       assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
       assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
@@ -1206,13 +1205,8 @@ static void putDReg(UInt dregNo, IRExpr * e)
       assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
       assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  /* hi */
       assign(t5, unop(Iop_64to32, mkexpr(t6)));    /* lo */
-#if defined (_MIPSEL)
       putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
       putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
-#elif defined (_MIPSEB)
-      putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
-      putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
-#endif
    }
 }
 
@@ -1895,7 +1889,7 @@ static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
 }
 
 /*------------------------------------------------------------*/
-/*--- Disassemble a single instruction                     ---*/
+/*---          Disassemble a single instruction            ---*/
 /*------------------------------------------------------------*/
 
 /* Disassemble a single instruction into IR. The instruction is
@@ -2360,23 +2354,17 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                      IRExpr *rm = get_IR_roundingmode();
                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
                                  rm, unop(Iop_ReinterpI32asF32,
-                                 mkU32(0x3F800000)), getLoFromF64(tyF,
+                                 mkU32(ONE_SINGLE)), getLoFromF64(tyF,
                                  getFReg(fs)))));
                      break;
                   }
                   case 0x11: {  /* D */
                      DIP("recip.d f%d, f%d\n", fd, fs);
-#if defined (_MIPSEL)
-                     IRExpr *rm = get_IR_roundingmode();
-                     putDReg(fd, triop(Iop_DivF64, rm, 
-                                 unop(Iop_ReinterpI64asF64,
-                                 mkU64(0x3FF0000000000000ULL)), getDReg(fs)));
-#elif defined (_MIPSEB)
                      IRExpr *rm = get_IR_roundingmode();
+                     /* putDReg(fd, 1.0/getDreg(fs)); */
                      putDReg(fd, triop(Iop_DivF64, rm,
                                  unop(Iop_ReinterpI64asF64,
-                                 mkU64(0x000000003FF00000ULL)), getDReg(fs)));
-#endif
+                                 mkU64(ONE_DOUBLE)), getDReg(fs)));
                      break;
                   }
                default:
@@ -3239,7 +3227,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                      DIP("rsqrt.s %d, %d\n", fd, fs);
                      IRExpr *rm = get_IR_roundingmode();
                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
-                                 unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)),
+                                 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
                                  binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
                                  getFReg(fs))))));
                      break;
@@ -3249,7 +3237,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                      IRExpr *rm = get_IR_roundingmode();
                      putDReg(fd, triop(Iop_DivF64, rm,
                                  unop(Iop_ReinterpI64asF64,
-                                 mkU64(0x3FF0000000000000ULL)),
+                                 mkU64(ONE_DOUBLE)),
                                  binop(Iop_SqrtF64, rm, getDReg(fs))));
                      break;
                   }
@@ -3615,38 +3603,54 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       break;
 
    case 0x22:  /* LWL */
-
       DIP("lwl r%d, %d(r%d)", rt, imm, rs);
       if (mode64) {
          /* t1 = addr */
-#if defined (_MIPSEL)
          t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
          assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+         /* t2 = word addr */
+         /* t4 = addr mod 4 */
+         LWX_SWX_PATTERN64;
+
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64,
+                          mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
+                    binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
+
+         /* rt content - adjusted */
+         t5 = newTemp(Ity_I32);
+         assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+                    binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+                    binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)),
+                    mkU8(0x3))))));
+
+         putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+                                             mkexpr(t3)), True));
 #elif defined (_MIPSEB)
-         t1 = newTemp(Ity_I64);
          assign(t1, binop(Iop_Xor64, mkU64(0x3),
                 binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))));
-#endif
-
          /* t2 = word addr */
          /* t4 = addr mod 4 */
          LWX_SWX_PATTERN64;
 
          /* t3 = word content - shifted */
          t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64,
+         assign(t3, binop(Iop_Shl32, unop(Iop_64HIto32, load(Ity_I64,
                           mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
                     binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
 
-         /* rt content  - adjusted */
+         /* rt content - adjusted */
          t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+         assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)),
                     binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
                     binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)),
                     mkU8(0x3))))));
 
          putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
                                              mkexpr(t3)), True));
+#endif
       } else {
          /* t1 = addr */
          t1 = newTemp(Ity_I32);
@@ -3658,7 +3662,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 #endif
 
          /* t2 = word addr */
-         /* t4 = addr mod 4 */
+         /* t4 = addr mod 8 */
          LWX_SWX_PATTERN;
 
          /* t3 = word content - shifted */
@@ -3678,36 +3682,51 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       break;
 
    case 0x26:  /* LWR */
-
       DIP("lwr r%d, %d(r%d)", rt, imm, rs);
       if (mode64) {
          /* t1 = addr */
-#if defined (_MIPSEL)
          t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
          assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+         /* t2 = word addr */
+         /* t4 = addr mod 8 */
+         LWX_SWX_PATTERN64;
+
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))),
+                    narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
+
+         /* rt content  - adjusted */
+         t5 = newTemp(Ity_I32);
+         assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+                unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
+                narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+         putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+                                       mkexpr(t3)), True));
 #elif defined (_MIPSEB)
-         t1 = newTemp(Ity_I64);
          assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs),
                           mkU64(extend_s_16to64(imm)))));
-#endif
-
          /* t2 = word addr */
          /* t4 = addr mod 4 */
          LWX_SWX_PATTERN64;
 
          /* t3 = word content - shifted */
          t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))),
+         assign(t3, binop(Iop_Shr32, unop(Iop_64HIto32, load(Ity_I64,mkexpr(t2))),
                     narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
 
          /* rt content  - adjusted */
          t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+         assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)),
                 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
                 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
 
          putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
                                        mkexpr(t3)), True));
+#endif
+
       } else {
          /* t1 = addr */
          t1 = newTemp(Ity_I32);
@@ -3798,7 +3817,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 #endif
 
       /* t2 = word addr */
-      /* t4 = addr mod 4 */
+      /* t4 = addr mod 8 */
       LWX_SWX_PATTERN64_1;
 
       /* t3 = rt content - shifted */
@@ -4549,7 +4568,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
          }
          break;
       case 0x3B: {  /* RDHWR */
-         DIP("rdhwr r%d, r%d\n", rt, rd);
+         DIP("rdhwr r%d, r%d", rt, rd);
             if (rd == 29) {
                putIReg(rt, getULR());
 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
@@ -6102,7 +6121,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                   mkU64(extend_s_16to64(imm)))));
 #endif
       /* t2 = word addr */
-      /* t4 = addr mod 4 */
+      /* t4 = addr mod 8 */
       LWX_SWX_PATTERN64_1;
 
       /* t3 = word content - shifted */
@@ -6138,11 +6157,11 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
 #elif defined (_MIPSEB)
       t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs),
+      assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
                                   mkU64(extend_s_16to64(imm)))));
 #endif
       /* t2 = word addr */
-      /* t4 = addr mod 4 */
+      /* t4 = addr mod 8 */
       LWX_SWX_PATTERN64_1;
 
       /* t3 = word content - shifted */
index 51d41a2acb12d5084c9ba10c400f054fc7dad8b1..cba7f1885aac9f155c668f5d6087931d0c2d7b43 100644 (file)
@@ -2734,11 +2734,13 @@ static Bool isLoadImm_EXACTLY2or6 ( UChar* p_to_check,
    return ret;
 }
 
-/* Generate a machine-word sized load or store.  Simplified version of
-   the Min_Load and Min_Store cases below. */
-static UChar* do_load_or_store_machine_word ( 
-                 UChar* p, Bool isLoad,
-                 UInt reg, MIPSAMode* am, Bool mode64 )
+/* Generate a machine-word sized load or store. Simplified version of
+   the Min_Load and Min_Store cases below.
+   This will generate 32-bit load/store on MIPS32, and 64-bit load/store on
+   MIPS64 platforms.
+*/
+static UChar* do_load_or_store_machine_word ( UChar* p, Bool isLoad, UInt reg,
+                                              MIPSAMode* am, Bool mode64 )
 {
    if (isLoad) { /* load */
       switch (am->tag) {
@@ -2778,6 +2780,49 @@ static UChar* do_load_or_store_machine_word (
    return p;
 }
 
+/* Generate a 32-bit sized load or store. Simplified version of
+   do_load_or_store_machine_word above. */
+static UChar* do_load_or_store_word32 ( UChar* p, Bool isLoad, UInt reg,
+                                        MIPSAMode* am, Bool mode64 )
+{
+   if (isLoad) { /* load */
+      switch (am->tag) {
+         case Mam_IR:
+            if (mode64) {
+               vassert(0 == (am->Mam.IR.index & 3));
+            }
+            p = doAMode_IR(p, 35, reg, am, mode64);
+            break;
+         case Mam_RR:
+            /* we could handle this case, but we don't expect to ever
+               need to. */
+            vassert(0);
+            break;
+         default:
+            vassert(0);
+            break;
+      }
+   } else /* store */ {
+      switch (am->tag) {
+         case Mam_IR:
+            if (mode64) {
+               vassert(0 == (am->Mam.IR.index & 3));
+            }
+            p = doAMode_IR(p, 43, reg, am, mode64);
+            break;
+         case Mam_RR:
+            /* we could handle this case, but we don't expect to ever
+               need to. */
+            vassert(0);
+            break;
+         default:
+            vassert(0);
+            break;
+      }
+   }
+   return p;
+}
+
 /* Move r_dst to r_src */
 static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src)
 {
@@ -3382,7 +3427,7 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
          }
 
          /* Update the guest PC. */
-         /* sw r-dstGA, amPC */
+         /* sw/sd r-dstGA, amPC */
          p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
                                            iregNo(i->Min.XIndir.dstGA, mode64),
                                            i->Min.XIndir.amPC, mode64);
@@ -4066,16 +4111,16 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
          */
          UChar* p0 = p;
          /* lw  r9, amCounter */
-         p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
+         p = do_load_or_store_word32(p, True /*isLoad*/ , /*r*/ 9,
                                      i->Min.EvCheck.amCounter, mode64);
          /* addiu r9,r9,-1 */
          p = mkFormI(p, 9, 9, 9, 0xFFFF);
          /* sw r30, amCounter */
-         p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 9,
+         p = do_load_or_store_word32(p, False /*!isLoad*/ , /*r*/ 9,
                                      i->Min.EvCheck.amCounter, mode64);
          /* bgez t9, nofail */
          p = mkFormI(p, 1, 9, 1, 3);
-         /* lw r9, amFailAddr */
+         /* lw/ld r9, amFailAddr */
          p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
                                            i->Min.EvCheck.amFailAddr, mode64);
          /* jalr $9 */
index f5045df2f49333e7fc8cbfaa2e4328735fba24fe..0187452c36e19fb1951d45f0d23f27a32b58991e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*---------------------------------------------------------------*/
-/*--- begin                                   host_mips_isel.c ---*/
+/*--- begin                                  host_mips_isel.c ---*/
 /*---------------------------------------------------------------*/
 
 /*
@@ -359,8 +359,13 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
    am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
 
    /* store hi,lo as Ity_I32's */
+#if defined (_MIPSEL)
    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
+#elif defined (_MIPSEB)
+   addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64));
+   addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64));
+#endif
 
    /* load as float */
    addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
@@ -2317,9 +2322,15 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
                                            am_addr));
             /* load as 2xI32 */
+#if defined (_MIPSEL)
             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
                                          mode64));
+#elif defined (_MIPSEB)
+            addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
+            addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
+                                         mode64));
+#endif
 
             /* Reset SP */
             add_to_sp(env, 16);
@@ -2436,7 +2447,7 @@ static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
             HReg r_dst = newVRegF(env);
 
             /* Move Doubleword to Floating Point
-               dmtc1 r_dst, valS */
+               dmtc1 r_dst, fr_src */
             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
 
             return r_dst;