]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips32/mips64: additional VEX support for FCSR register.
authorDejan Jevtic <dejan.jevtic@valgrind.org>
Wed, 18 Sep 2013 10:06:13 +0000 (10:06 +0000)
committerDejan Jevtic <dejan.jevtic@valgrind.org>
Wed, 18 Sep 2013 10:06:13 +0000 (10:06 +0000)
Some mips fpu instructions are changing the value of the
fcsr register so we need to update the value of the fcsr
register in the guest state.

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

VEX/priv/guest_mips_defs.h
VEX/priv/guest_mips_helpers.c
VEX/priv/guest_mips_toIR.c
VEX/priv/host_mips_isel.c

index 2ab3868b764f908909deff990321b416403678e6..b7fe1fb56cc11981bcafd24cfbc20539e6d02e49 100644 (file)
@@ -78,6 +78,15 @@ extern VexGuestLayout mips64Guest_layout;
 /*---------------------------------------------------------*/
 /*---                mips guest helpers                 ---*/
 /*---------------------------------------------------------*/
+typedef enum {
+   CEILWS=0, CEILWD,  CEILLS,  CEILLD,
+   FLOORWS,  FLOORWD, FLOORLS, FLOORLD,
+   ROUNDWS,  ROUNDWD, ROUNDLS, ROUNDLD,
+   TRUNCWS,  TRUNCWD, TRUNCLS, TRUNCLD,
+   CVTDS,    CVTDW,   CVTSD,   CVTSW,
+   CVTWS,    CVTWD,   CVTDL,   CVTLS,
+   CVTLD,    CVTSL
+} flt_op;
 
 extern UInt mips32_dirtyhelper_mfc0 ( UInt rd, UInt sel );
 
@@ -88,6 +97,9 @@ extern ULong mips64_dirtyhelper_dmfc0 ( UInt rd, UInt sel );
 extern ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd );
 #endif
 
+extern UInt mips_dirtyhelper_calculate_FCSR ( void* guest_state, UInt fs,
+                                              flt_op op );
+
 /*---------------------------------------------------------*/
 /*---               Condition code stuff                ---*/
 /*---------------------------------------------------------*/
index 1e2c20b3a87b4b9aa8a032618acacd43f738a330..0a2e5ee2e109d6ba792854aaf4241fa954a46d4a 100644 (file)
@@ -1092,6 +1092,128 @@ ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd )
 }
 #endif
 
+#define ASM_VOLATILE_ROUND32(fs, inst)                              \
+   __asm__ volatile("ctc1    %3,  $31"  "\n\t"                      \
+                    "mtc1    %1,  $f0"  "\n\t"                      \
+                    "mtc1    %2,  $f1"  "\n\t"                      \
+                    ""#inst" $f0, $f0"  "\n\t"                      \
+                    "cfc1    %0,  $31"  "\n\t"                      \
+                    : "=r" (ret)                                    \
+                    : "r" (addr[fs]), "r" (addr[fs+1]), "r" (fcsr)  \
+                    : "$f0", "$f1"                                  \
+                   );
+
+#define ASM_VOLATILE_ROUND64(fs, inst)                              \
+   __asm__ volatile("ctc1     %2,  $31"  "\n\t"                     \
+                    "dmtc1    %1,  $f0"  "\n\t"                     \
+                    ""#inst"  $f0, $f0"  "\n\t"                     \
+                    "cfc1     %0,  $31"  "\n\t"                     \
+                    : "=r" (ret)                                    \
+                    : "r" (addr[fs]), "r" (fcsr)                    \
+                    : "$f0"                                         \
+                   );
+
+/* TODO: Add cases for all fpu instructions because all fpu instructions are
+         change the value of FCSR register. */
+extern UInt mips_dirtyhelper_calculate_FCSR ( void* gs, UInt fs, flt_op inst )
+{
+   UInt ret = 0;
+#if defined(VGA_mips32)
+   VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
+   UInt *addr = (UInt *)&guest_state->guest_f0;
+#define ASM_VOLATILE_ROUND(fs, inst) ASM_VOLATILE_ROUND32(fs, inst)
+#else
+   VexGuestMIPS64State* guest_state = (VexGuestMIPS64State*)gs;
+   ULong *addr = (ULong *)&guest_state->guest_f0;
+#define ASM_VOLATILE_ROUND(fs, inst) ASM_VOLATILE_ROUND64(fs, inst)
+#endif
+   UInt fcsr = guest_state->guest_FCSR;
+   switch (inst) {
+      case ROUNDWD:
+         ASM_VOLATILE_ROUND(fs, round.w.d)
+         break;
+      case FLOORWS:
+         ASM_VOLATILE_ROUND(fs, floor.w.s)
+         break;
+      case FLOORWD:
+         ASM_VOLATILE_ROUND(fs, floor.w.d)
+         break;
+      case TRUNCWS:
+         ASM_VOLATILE_ROUND(fs, trunc.w.s)
+         break;
+      case TRUNCWD:
+         ASM_VOLATILE_ROUND(fs, trunc.w.d)
+         break;
+      case CEILWS:
+         ASM_VOLATILE_ROUND(fs, ceil.w.s)
+         break;
+      case CEILWD:
+         ASM_VOLATILE_ROUND(fs, ceil.w.d)
+         break;
+      case CEILLS:
+         ASM_VOLATILE_ROUND(fs, ceil.l.s)
+         break;
+      case CEILLD:
+         ASM_VOLATILE_ROUND(fs, ceil.l.d)
+         break;
+      case ROUNDLS:
+         ASM_VOLATILE_ROUND(fs, round.l.s)
+         break;
+      case ROUNDLD:
+         ASM_VOLATILE_ROUND(fs, round.l.d)
+         break;
+      case TRUNCLS:
+         ASM_VOLATILE_ROUND(fs, trunc.l.s)
+         break;
+      case TRUNCLD:
+         ASM_VOLATILE_ROUND(fs, trunc.l.d)
+         break;
+      case CVTDS:
+         ASM_VOLATILE_ROUND(fs, cvt.d.s)
+         break;
+      case CVTDW:
+         ASM_VOLATILE_ROUND(fs, cvt.d.w)
+         break;
+      case CVTDL:
+         ASM_VOLATILE_ROUND(fs, cvt.d.l)
+         break;
+      case CVTSW:
+         ASM_VOLATILE_ROUND(fs, cvt.s.w)
+         break;
+      case CVTSD:
+         ASM_VOLATILE_ROUND(fs, cvt.s.d)
+         break;
+      case CVTSL:
+         ASM_VOLATILE_ROUND(fs, cvt.s.l)
+         break;
+      case CVTWS:
+         ASM_VOLATILE_ROUND(fs, cvt.w.s)
+         break;
+      case CVTWD:
+         ASM_VOLATILE_ROUND(fs, cvt.w.d)
+         break;
+      case CVTLS:
+         ASM_VOLATILE_ROUND(fs, cvt.l.s)
+         break;
+      case CVTLD:
+         ASM_VOLATILE_ROUND(fs, cvt.l.d)
+         break;
+      case FLOORLS:
+         ASM_VOLATILE_ROUND(fs, floor.l.s)
+         break;
+      case FLOORLD:
+         ASM_VOLATILE_ROUND(fs, floor.l.d)
+         break;
+      case ROUNDWS:
+         ASM_VOLATILE_ROUND(fs, round.w.s)
+         break;
+      default:
+         vassert(0);
+         break;
+   }
+   return ret;
+}
+
 /*---------------------------------------------------------------*/
 /*--- end                                guest_mips_helpers.c ---*/
 /*---------------------------------------------------------------*/
index b3917b62c38337e647774fcb6481c1a3b2cbb9f1..6f7eca9184024bd89a6f1e3fd67e08dee1ea0902 100644 (file)
@@ -1088,6 +1088,41 @@ static void putFCSR(IRExpr * e)
       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
 }
 
+static void calculateFCSR(UInt fs, UInt inst)
+{
+   IRDirty *d;
+   IRTemp fcsr = newTemp(Ity_I32);
+   /* IRExpr_BBPTR() => Need to pass pointer to guest
+      state to helper. */
+   d = unsafeIRDirty_1_N(fcsr, 0,
+                         "mips_dirtyhelper_calculate_FCSR",
+                         &mips_dirtyhelper_calculate_FCSR,
+                         mkIRExprVec_3(IRExpr_BBPTR(),
+                                       mkU32(fs),
+                                       mkU32(inst)));
+
+   /* Declare we're reading guest state. */
+   d->nFxState = mode64 ? 1 : 2;
+   vex_bzero(&d->fxState, sizeof(d->fxState));
+
+   d->fxState[0].fx     = Ifx_Read;  /* read */
+   d->fxState[0].offset = floatGuestRegOffset(fs);
+   if (mode64)
+      d->fxState[0].size   = sizeof(ULong);
+   else
+      d->fxState[0].size   = sizeof(UInt);
+
+   if (!mode64) {
+      d->fxState[1].fx     = Ifx_Read;  /* read */
+      d->fxState[1].offset = floatGuestRegOffset(fs+1);
+      d->fxState[1].size   = sizeof(UInt);
+   }
+
+   stmt(IRStmt_Dirty(d));
+
+   putFCSR(mkexpr(fcsr));
+}
+
 static IRExpr *getULR(void)
 {
    if (mode64)
@@ -11658,6 +11693,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("round.l.s f%d, f%d", fd, fs);
+                     calculateFCSR(fs, ROUNDLS);
                      t0 = newTemp(Ity_I64);
 
                      assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
@@ -11667,6 +11703,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                   break;
                   case 0x11:  /* D */
                      DIP("round.l.d f%d, f%d", fd, fs);
+                     calculateFCSR(fs, ROUNDLD);
                      putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0),
                                        getFReg(fs)));
                      break;
@@ -11680,6 +11717,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("trunc.l.s f%d, f%d", fd, fs);
+                     calculateFCSR(fs, TRUNCLS);
                      t0 = newTemp(Ity_I64);
                      assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
                                       getLoFromF64(Ity_F64, getFReg(fs))));
@@ -11688,6 +11726,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                      break;
                   case 0x11:  /* D */
                      DIP("trunc.l.d f%d, f%d", fd, fs);
+                     calculateFCSR(fs, TRUNCLD);
                      putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3),
                                        getFReg(fs)));
                      break;
@@ -12155,6 +12194,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("cvt.d.s f%d, f%d", fd, fs);
+                     calculateFCSR(fs, CVTDS);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12168,14 +12208,13 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                         assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
 
                         putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
-                        break;
-                     } else {
+                     } else
                         putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
-                        break;
-                     }
+                     break;
 
                   case 0x14:
                      DIP("cvt.d.w %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTDW);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12197,6 +12236,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                   case 0x15: {  /* L */
                      if (mode64) {
                         DIP("cvt.d.l %d, %d", fd, fs);
+                        calculateFCSR(fs, CVTDL);
                         t0 = newTemp(Ity_I64);
                         assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
 
@@ -12215,6 +12255,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x14:  /* W */
                      DIP("cvt.s.w %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTSW);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12226,17 +12267,17 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                         assign(t1, unop(Iop_64to32, mkexpr(t0)));
                         putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
                                     get_IR_roundingmode(), mkexpr(t1))));
-                        break;
                      } else {
                         t0 = newTemp(Ity_I32);
                         assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
                         putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
                                     mkexpr(t0)));
-                        break;
-                    }
+                     }
+                     break;
 
                   case 0x11:  /* D */
                      DIP("cvt.s.d %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTSD);
                      if (mode64) {
                         t0 = newTemp(Ity_F32);
                         assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
@@ -12249,6 +12290,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                   case 0x15:  /* L */
                      DIP("cvt.s.l %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTSL);
                      t0 = newTemp(Ity_I64);
                      assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
 
@@ -12265,6 +12307,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                case 0x10:  /* S */
                   DIP("cvt.w.s %d, %d", fd, fs);
+                  calculateFCSR(fs, CVTWS);
                   if (mode64) {
                      putFReg(fd, mkWidenFromF32(tyF, binop(Iop_RoundF32toInt,
                              get_IR_roundingmode(), getLoFromF64(tyF,
@@ -12276,6 +12319,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                case 0x11:
                   DIP("cvt.w.d %d, %d", fd, fs);
+                  calculateFCSR(fs, CVTWD);
                   if (mode64) {
                      t0 = newTemp(Ity_I32);
                      t1 = newTemp(Ity_F32);
@@ -12303,6 +12347,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("cvt.l.s %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTLS);
                      t0 = newTemp(Ity_I64);
 
                      assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
@@ -12313,6 +12358,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                   case 0x11: {  /* D */
                      DIP("cvt.l.d %d, %d", fd, fs);
+                     calculateFCSR(fs, CVTLD);
                      putFReg(fd, binop(Iop_RoundF64toInt,
                              get_IR_roundingmode(), getFReg(fs)));
                      break;
@@ -12327,6 +12373,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("floor.l.s %d, %d", fd, fs);
+                     calculateFCSR(fs, FLOORLS);
                      t0 = newTemp(Ity_I64);
 
                      assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
@@ -12337,6 +12384,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                   case 0x11:  /* D */
                      DIP("floor.l.d %d, %d", fd, fs);
+                     calculateFCSR(fs, FLOORLD);
                      putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1),
                                        getFReg(fs)));
                      break;
@@ -12349,6 +12397,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("round.w.s f%d, f%d", fd, fs);
+                     calculateFCSR(fs, ROUNDWS);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12365,22 +12414,20 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                          mkexpr(t3)));
 
                         putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
-                        break;
-                     } else {
+                     } else
                         putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0),
                                           getFReg(fs)));
-                        break;
-                     }
+                     break;
 
                   case 0x11:  /* D */
                      DIP("round.w.d f%d, f%d", fd, fs);
+                     calculateFCSR(fs, ROUNDWD);
                      if (mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
                                          getDReg(fs)));
                         putFReg(fd, mkWidenFromF32(tyF,
                                     unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                        break;
                      } else {
                         t0 = newTemp(Ity_I32);
 
@@ -12388,8 +12435,8 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                          getDReg(fs)));
 
                         putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                        break;
                      }
+                     break;
                   default:
                      goto decode_failure;
 
@@ -12400,6 +12447,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("floor.w.s f%d, f%d", fd, fs);
+                     calculateFCSR(fs, FLOORWS);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12416,15 +12464,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                          mkexpr(t3)));
 
                         putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
-                        break;
-                     } else {
+                     } else
                         putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1),
                                          getFReg(fs)));
-                        break;
-                     }
+                     break;
 
                   case 0x11:  /* D */
                      DIP("floor.w.d f%d, f%d", fd, fs);
+                     calculateFCSR(fs, FLOORWD);
                      if (mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
@@ -12451,6 +12498,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("trunc.w.s %d, %d", fd, fs);
+                     calculateFCSR(fs, TRUNCWS);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12467,14 +12515,13 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                          mkexpr(t3)));
 
                         putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
-                        break;
-                     } else {
+                     } else
                         putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3),
                                        getFReg(fs)));
                      break;
-                  }
                   case 0x11:  /* D */
                      DIP("trunc.w.d %d, %d", fd, fs);
+                     calculateFCSR(fs, TRUNCWD);
                      if (mode64) {
                         t0 = newTemp(Ity_I32);
 
@@ -12483,7 +12530,6 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                         putFReg(fd, mkWidenFromF32(tyF,
                                     unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                        break;
                      } else {
                         t0 = newTemp(Ity_I32);
 
@@ -12491,8 +12537,8 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                                          getDReg(fs)));
 
                         putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                        break;
                      }
+                     break;
                   default:
                      goto decode_failure;
 
@@ -12503,6 +12549,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("ceil.w.s %d, %d", fd, fs);
+                     calculateFCSR(fs, CEILWS);
                      if (mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
@@ -12526,20 +12573,20 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                   case 0x11:  /* D */
                      DIP("ceil.w.d %d, %d", fd, fs);
+                     calculateFCSR(fs, CEILWD);
                      if (!mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
                                          getDReg(fs)));
                         putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                        break;
                      } else {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
                                          getDReg(fs)));
                         putFReg(fd, mkWidenFromF32(tyF,
                                     unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                        break;
                      }
+                     break;
                   default:
                      goto decode_failure;
 
@@ -12550,6 +12597,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("ceil.l.s %d, %d", fd, fs);
+                     calculateFCSR(fs, CEILLS);
                      t0 = newTemp(Ity_I64);
 
                      assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
@@ -12560,6 +12608,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
 
                   case 0x11:  /* D */
                      DIP("ceil.l.d %d, %d", fd, fs);
+                     calculateFCSR(fs, CEILLD);
                      putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2),
                                        getFReg(fs)));
                      break;
index d59b4ab166d862dc08eb277c351a4f343bcb178c..06c1eb5439734c6206b7ab904f5f249b43ccbd96 100644 (file)
@@ -554,7 +554,7 @@ static void doHelperCall(/*OUT*/UInt*   stackAdjustAfterCall,
          if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
             aTy  = typeOfIRExpr(env->type_env, arg);
 
-         if (aTy == Ity_I32 || mode64) {
+         if (aTy == Ity_I32 || (mode64 && arg->tag != Iex_BBPTR)) {
             tmpregs[argreg] = iselWordExpr_R(env, arg);
             argreg++;
          } else if (aTy == Ity_I64) {  /* Ity_I64 */
@@ -569,7 +569,6 @@ static void doHelperCall(/*OUT*/UInt*   stackAdjustAfterCall,
             tmpregs[argreg] = raHi;
             argreg++;
          } else if (arg->tag == Iex_BBPTR) {
-            vassert(0);  // ATC
             tmpregs[argreg] = GuestStatePointer(mode64);
             argreg++;
          }