]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips64: support for fp32 mode
authorPetar Jovanovic <mips32r2@gmail.com>
Tue, 4 Oct 2016 14:27:18 +0000 (14:27 +0000)
committerPetar Jovanovic <mips32r2@gmail.com>
Tue, 4 Oct 2016 14:27:18 +0000 (14:27 +0000)
Support for FP32 emulation on MIPS64 platforms
(including prctl(GET/SET_FP_MODE) syscalls).

Patch by Aleksandar Rikalo.

Implements the remaining parts for BZ #366079.

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

VEX/priv/guest_mips_toIR.c

index c3228315f1b4fa0bfcf6ef279539a711d9ddcb5b..aaa07fa08d4675811465207e9abddb6a6d890f36 100644 (file)
@@ -1429,8 +1429,8 @@ static IRExpr *getDReg(UInt dregNo)
       IRTemp t4 = newTemp(Ity_I32);
       IRTemp t5 = newTemp(Ity_I64);
 
-      assign(t0, getFReg(dregNo));
-      assign(t1, getFReg(dregNo + 1));
+      assign(t0, getFReg(dregNo & (~1)));
+      assign(t1, getFReg(dregNo | 1));
 
       assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
       assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
@@ -1467,8 +1467,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 */
-      putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
-      putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
+      putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
+      putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
    }
 }
 
@@ -12236,7 +12236,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
                putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
                break;
-            } else if ((fs & 1) == 0) {
+            } else {
                putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
                                                   getFReg(fs | 1)), True));
                break;
@@ -12254,7 +12254,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                      getLoFromF64(Ity_F64, getDReg(fs)))));
                putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
                break;
-            } else if ((fs & 1) == 0) {
+            } else {
                putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
                                     mkNarrowTo32(ty, getIReg(rt))));
                break;
@@ -12536,55 +12536,25 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                case 0x10:  /* S */
                   DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
-                  t1 = newTemp(Ity_F64);
-                  t2 = newTemp(Ity_F64);
-                  t3 = newTemp(Ity_I1);
-                  t4 = newTemp(Ity_F64);
-                  if (mode64) {
-                     assign(t1, getFReg(fs));
-                     assign(t2, getFReg(fd));
-                     assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
-                  } else {
-                     if (fp_mode64) {
-                        assign(t1, getFReg(fs));
-                        assign(t2, getFReg(fd));
-                        assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
-                     } else {
-                        assign(t1, unop(Iop_F32toF64, getFReg(fs)));
-                        assign(t2, unop(Iop_F32toF64, getFReg(fd)));
-                        assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
-                     }
-                  }
-
-                  assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2)));
-                  if (fp_mode64) {
-                     IRTemp f = newTemp(Ity_F64);
-                     IRTemp fd_hi = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-                     assign(f, getFReg(fd));
-                     assign(fd_hi, unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
-                                        mkexpr(f))));
+                  t1 = newTemp(Ity_I1);
 
-                     assign(t5, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
-                                unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
+                  if (mode64)
+                     assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+                  else
+                     assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
 
-                     putFReg(fd, unop (Iop_ReinterpI64asF64, mkexpr(t5)));
-                  } else
-                     putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                       mkexpr(t4)));
+                  putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
                   break;
                case 0x11:  /* D */
                   DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
-
-                  t3 = newTemp(Ity_I1);
-                  t4 = newTemp(Ity_F64);
+                  t1 = newTemp(Ity_I1);
 
                   if (mode64)
-                     assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+                     assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
                   else
-                     assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
+                     assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
 
-                  putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd)));
+                  putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
                   break;
                default:
                   goto decode_failure;
@@ -12595,51 +12565,25 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                case 0x10:  /* S */
                   DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
+                  t1 = newTemp(Ity_I1);
 
-                  t1 = newTemp(Ity_F64);
-                  t2 = newTemp(Ity_F64);
-                  t3 = newTemp(Ity_I1);
-                  t4 = newTemp(Ity_F64);
-                  if (fp_mode64) {
-                     assign(t1, getFReg(fs));
-                     assign(t2, getFReg(fd));
-                     if (mode64)
-                        assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
-                     else
-                        assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
-                  } else {
-                     assign(t1, unop(Iop_F32toF64, getFReg(fs)));
-                     assign(t2, unop(Iop_F32toF64, getFReg(fd)));
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
-                  }
-                  assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2)));
-
-                 if (fp_mode64) {
-                     IRTemp f = newTemp(Ity_F64);
-                     IRTemp fd_hi = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I64);
-                     assign(f, getFReg(fd));
-                     assign(fd_hi, unop(Iop_64HIto32,
-                                   unop(Iop_ReinterpF64asI64, mkexpr(f))));
-                     assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
-                                unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
-
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
-                  } else
-                     putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                       mkexpr(t4)));
+                  if (mode64)
+                     assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+                  else
+                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
 
+                  putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
                   break;
                case 0x11:  /* D */
                   DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
-                  t3 = newTemp(Ity_I1);
-                  t4 = newTemp(Ity_F64);
+                  t1 = newTemp(Ity_I1);
+
                   if (mode64)
-                     assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+                     assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
                   else
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
+                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
 
-                  putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd)));
+                  putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
                   break;
                default:
                   goto decode_failure;
@@ -12840,13 +12784,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                      putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
                   } else
-                     putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt)));
+                     putFReg(fs, unop(Iop_ReinterpI32asF32,
+                                      mkNarrowTo32(ty, getIReg(rt))));
                   break;
 
                case 0x5:  /* Doubleword Move to Floating Point DMTC1; MIPS64 */
                   DIP("dmtc1 r%u, f%u", rt, fs);
                   vassert(mode64);
-                  putFReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
+                  putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
                   break;
 
                case 0x0:  /* MFC1 */
@@ -12858,13 +12803,15 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                      assign(t1, unop(Iop_64to32, mkexpr(t0)));
                      putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
                   } else
-                     putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                     putIReg(rt, mkWidenFrom32(ty,
+                                 unop(Iop_ReinterpF32asI32, getFReg(fs)),
+                                 True));
                   break;
 
                case 0x1:  /* Doubleword Move from Floating Point DMFC1;
                              MIPS64 */
                   DIP("dmfc1 r%u, f%u", rt, fs);
-                  putIReg(rt, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+                  putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
                   break;
 
                case 0x6:  /* CTC1 */
@@ -13476,29 +13423,16 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
    case 0x31:  /* LWC1 */
       /* Load Word to Floating Point - LWC1 (MIPS32) */
       DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
+      LOAD_STORE_PATTERN;
       if (fp_mode64) {
-         t1 = newTemp(Ity_F32);
+         t0 = newTemp(Ity_F32);
          t2 = newTemp(Ity_I64);
-         if (mode64) {
-            t0 = newTemp(Ity_I64);
-            /* new LO */
-            assign(t0, binop(Iop_Add64, getIReg(rs),
-                             mkU64(extend_s_16to64(imm))));
-         } else {
-            t0 = newTemp(Ity_I32);
-            /* new LO */
-            assign(t0, binop(Iop_Add32, getIReg(rs),
-                             mkU32(extend_s_16to32(imm))));
-         }
-         assign(t1, load(Ity_F32, mkexpr(t0)));
+         assign(t0, load(Ity_F32, mkexpr(t1)));
          assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
-                                                mkexpr(t1)), True));
+                                                mkexpr(t0)), True));
          putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
       } else {
-         t0 = newTemp(Ity_I32);
-         assign(t0, binop(Iop_Add32, getIReg(rs),
-                           mkU32(extend_s_16to32(imm))));
-         putFReg(ft, load(Ity_F32, mkexpr(t0)));
+         putFReg(ft, load(Ity_F32, mkexpr(t1)));
       }
       break;
 
@@ -13591,16 +13525,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       case 0x0: {  /* LWXC1 */
          /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
          DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
+         t2 = newTemp(ty);
+         assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                          getIReg(rt)));
          if (fp_mode64) {
             t0 = newTemp(Ity_I64);
             t1 = newTemp(Ity_I32);
             t3 = newTemp(Ity_F32);
             t4 = newTemp(Ity_I64);
-
-            t2 = newTemp(ty);
-            /* new LO */
-            assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                             getIReg(rt)));
             assign(t3, load(Ity_F32, mkexpr(t2)));
 
             assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
@@ -13608,9 +13540,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
             putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
          } else {
-            t0 = newTemp(Ity_I32);
-            assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
-            putFReg(fd, load(Ity_F32, mkexpr(t0)));
+            putFReg(fd, load(Ity_F32, mkexpr(t2)));
          }
          break;
       }
@@ -13618,29 +13548,12 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       case 0x1: {  /* LDXC1 */
          /* Load Doubleword  Indexed to Floating Point
             LDXC1 (MIPS32r2 and MIPS64) */
-         if (fp_mode64) {
-            DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
-            t0 = newTemp(ty);
-            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                             getIReg(rt)));
-            putFReg(fd, load(Ity_F64, mkexpr(t0)));
-            break;
-         } else {
-            t0 = newTemp(Ity_I32);
-            assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
-
-            t1 = newTemp(Ity_I32);
-            assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
-
-#if defined (_MIPSEL)
-            putFReg(fd, load(Ity_F32, mkexpr(t0)));
-            putFReg(fd + 1, load(Ity_F32, mkexpr(t1)));
-#elif defined (_MIPSEB)
-            putFReg(fd + 1, load(Ity_F32, mkexpr(t0)));
-            putFReg(fd, load(Ity_F32, mkexpr(t1)));
-#endif
-            break;
-         }
+         DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
+         t0 = newTemp(ty);
+         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                          getIReg(rt)));
+         putDReg(fd, load(Ity_F64, mkexpr(t0)));
+         break;
       }
 
       case 0x5:  /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
@@ -13656,42 +13569,22 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
       case 0x8: {  /* Store Word Indexed from Floating Point - SWXC1 */
          DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
+         t0 = newTemp(ty);
+         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                          getIReg(rt)));
          if (fp_mode64) {
-            t0 = newTemp(ty);
-            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                             getIReg(rt)));
             store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
-
          } else {
-            t0 = newTemp(Ity_I32);
-            assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
-
             store(mkexpr(t0), getFReg(fs));
          }
          break;
       }
       case 0x9: {  /* Store Doubleword Indexed from Floating Point - SDXC1 */
-         DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
-         if (fp_mode64) {
-            t0 = newTemp(ty);
-            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                             getIReg(rt)));
-            store(mkexpr(t0), getFReg(fs));
-         } else {
-            t0 = newTemp(Ity_I32);
-            assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
-
-            t1 = newTemp(Ity_I32);
-            assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
-
-#if defined (_MIPSEL)
-            store(mkexpr(t0), getFReg(fs));
-            store(mkexpr(t1), getFReg(fs + 1));
-#elif defined (_MIPSEB)
-            store(mkexpr(t0), getFReg(fs + 1));
-            store(mkexpr(t1), getFReg(fs));
-#endif
-         }
+         DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
+         t0 = newTemp(ty);
+         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                          getIReg(rt)));
+         store(mkexpr(t0), getDReg(fs));
          break;
       }
       case 0xD:  /* Store Doubleword Indexed Unaligned from Floating Point -