mips32: VEX Support for 64bit FPU on MIPS32 platforms.

This patch is adding support for mips32 with 64bit FPU.
Assume that floating-point registers are 64 bits wide.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2821 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_mips_defs.h b/priv/guest_mips_defs.h
index dc7163c..da112c5 100644
--- a/priv/guest_mips_defs.h
+++ b/priv/guest_mips_defs.h
@@ -99,8 +99,12 @@
 extern ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd );
 #endif
 
-extern UInt mips_dirtyhelper_calculate_FCSR ( void* guest_state, UInt fs,
-                                              UInt ft, flt_op op );
+/* Calculate FCSR in fp32 mode. */
+extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* guest_state, UInt fs,
+                                                   UInt ft, flt_op op );
+/* Calculate FCSR in fp64 mode. */
+extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* guest_state, UInt fs,
+                                                   UInt ft, flt_op op );
 
 /*---------------------------------------------------------*/
 /*---               Condition code stuff                ---*/
diff --git a/priv/guest_mips_helpers.c b/priv/guest_mips_helpers.c
index 9e47bc7..9258016 100644
--- a/priv/guest_mips_helpers.c
+++ b/priv/guest_mips_helpers.c
@@ -44,7 +44,7 @@
    these functions are generated by the back end.
 */
 
-#define ALWAYSDEFD32(field)                           \
+#define ALWAYSDEFD32(field)                            \
     { offsetof(VexGuestMIPS32State, field),            \
       (sizeof ((VexGuestMIPS32State*)0)->field) }
 
@@ -1133,14 +1133,14 @@
                    );
 
 #define ASM_VOLATILE_UNARY64(inst)                                  \
-   __asm__ volatile("cfc1   $t0,  $31"   "\n\t"                     \
-                    "ctc1   %2,   $31"   "\n\t"                     \
-                    "dmtc1  %1,   $f24"  "\n\t"                     \
-                    #inst"  $f24, $f24"  "\n\t"                     \
-                    "cfc1   %0,   $31"   "\n\t"                     \
-                    "ctc1   $t0,  $31"   "\n\t"                     \
+   __asm__ volatile("cfc1  $t0,  $31"    "\n\t"                     \
+                    "ctc1  %2,   $31"    "\n\t"                     \
+                    "ldc1  $f24, 0(%1)"  "\n\t"                     \
+                    #inst" $f24, $f24"   "\n\t"                     \
+                    "cfc1  %0,   $31"    "\n\t"                     \
+                    "ctc1  $t0,  $31"    "\n\t"                     \
                     : "=r" (ret)                                    \
-                    : "r" (fsVal), "r" (fcsr)                       \
+                    : "r" (&(addr[fs])), "r" (fcsr)                 \
                     : "t0", "$f24"                                  \
                    );
 
@@ -1173,144 +1173,257 @@
                     : "t0", "$f20", "$f21", "$f22", "$f23"          \
                    );
 
-#define ASM_VOLATILE_BINARY64(inst)                                 \
-   __asm__ volatile("cfc1  $t0,  $31"         "\n\t"                \
-                    "ctc1  %3,   $31"         "\n\t"                \
-                    "dmtc1 %1,   $f24"        "\n\t"                \
-                    "dmtc1 %2,   $f25"        "\n\t"                \
-                    #inst" $f24, $f24, $f25"  "\n\t"                \
-                    "cfc1  %0,   $31"         "\n\t"                \
-                    "ctc1  $t0,  $31"         "\n\t"                \
-                    : "=r" (ret)                                    \
-                    : "r" (fsVal), "r" (ftVal), "r" (fcsr)          \
-                    : "t0", "$f24", "$f25"                          \
+#define ASM_VOLATILE_BINARY64(inst)                                     \
+   __asm__ volatile("cfc1  $t0,  $31"         "\n\t"                    \
+                    "ctc1  %3,   $31"         "\n\t"                    \
+                    "ldc1  $f24, 0(%1)"       "\n\t"                    \
+                    "ldc1  $f26, 0(%2)"       "\n\t"                    \
+                    #inst" $f24, $f24, $f26"  "\n\t"                    \
+                    "cfc1  %0,   $31"         "\n\t"                    \
+                    "ctc1  $t0,  $31"         "\n\t"                    \
+                    : "=r" (ret)                                        \
+                    : "r" (&(addr[fs])), "r" (&(addr[ft])), "r" (fcsr)  \
+                    : "t0", "$f24", "$f26"                              \
                    );
 
 /* 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, UInt ft,
-                                              flt_op inst )
+extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* gs, UInt fs, UInt ft,
+                                                   flt_op inst )
+{
+   UInt ret = 0;
+#if defined(__mips__)
+   VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
+   UInt loFsVal, hiFsVal, loFtVal, hiFtVal;
+#if defined (_MIPSEL)
+   ULong *addr = (ULong *)&guest_state->guest_f0;
+   loFsVal     = (UInt)addr[fs];
+   hiFsVal     = (UInt)addr[fs+1];
+   loFtVal     = (UInt)addr[ft];
+   hiFtVal     = (UInt)addr[ft+1];
+#elif defined (_MIPSEB)
+   UInt *addr = (UInt *)&guest_state->guest_f0;
+   loFsVal    = (UInt)addr[fs*2];
+   hiFsVal    = (UInt)addr[fs*2+2];
+   loFtVal    = (UInt)addr[ft*2];
+   hiFtVal    = (UInt)addr[ft*2+2];
+#endif
+   UInt fcsr     = guest_state->guest_FCSR;
+   switch (inst) {
+      case ROUNDWD:
+         ASM_VOLATILE_UNARY32_DOUBLE(round.w.d)
+         break;
+      case FLOORWS:
+         ASM_VOLATILE_UNARY32(floor.w.s)
+         break;
+      case FLOORWD:
+         ASM_VOLATILE_UNARY32_DOUBLE(floor.w.d)
+         break;
+      case TRUNCWS:
+         ASM_VOLATILE_UNARY32(trunc.w.s)
+         break;
+      case TRUNCWD:
+         ASM_VOLATILE_UNARY32_DOUBLE(trunc.w.d)
+         break;
+      case CEILWS:
+         ASM_VOLATILE_UNARY32(ceil.w.s)
+         break;
+      case CEILWD:
+         ASM_VOLATILE_UNARY32_DOUBLE(ceil.w.d)
+         break;
+      case CVTDS:
+         ASM_VOLATILE_UNARY32(cvt.d.s)
+         break;
+      case CVTDW:
+         ASM_VOLATILE_UNARY32(cvt.d.w)
+         break;
+      case CVTSW:
+         ASM_VOLATILE_UNARY32(cvt.s.w)
+         break;
+      case CVTSD:
+         ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.d)
+         break;
+      case CVTWS:
+         ASM_VOLATILE_UNARY32(cvt.w.s)
+         break;
+      case CVTWD:
+         ASM_VOLATILE_UNARY32_DOUBLE(cvt.w.d)
+         break;
+      case ROUNDWS:
+         ASM_VOLATILE_UNARY32(round.w.s)
+         break;
+#if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
+    || (__mips == 64)
+      case CEILLS:
+         ASM_VOLATILE_UNARY32(ceil.l.s)
+         break;
+      case CEILLD:
+         ASM_VOLATILE_UNARY32_DOUBLE(ceil.l.d)
+         break;
+      case CVTDL:
+         ASM_VOLATILE_UNARY32_DOUBLE(cvt.d.l)
+         break;
+      case CVTLS:
+         ASM_VOLATILE_UNARY32(cvt.l.s)
+         break;
+      case CVTLD:
+         ASM_VOLATILE_UNARY32_DOUBLE(cvt.l.d)
+         break;
+      case CVTSL:
+         ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.l)
+         break;
+      case FLOORLS:
+         ASM_VOLATILE_UNARY32(floor.l.s)
+         break;
+      case FLOORLD:
+         ASM_VOLATILE_UNARY32_DOUBLE(floor.l.d)
+         break;
+      case ROUNDLS:
+         ASM_VOLATILE_UNARY32(round.l.s)
+         break;
+      case ROUNDLD:
+         ASM_VOLATILE_UNARY32_DOUBLE(round.l.d)
+         break;
+      case TRUNCLS:
+         ASM_VOLATILE_UNARY32(trunc.l.s)
+         break;
+      case TRUNCLD:
+         ASM_VOLATILE_UNARY32_DOUBLE(trunc.l.d)
+         break;
+#endif
+      case ADDS:
+          ASM_VOLATILE_BINARY32(add.s)
+          break;
+      case ADDD:
+          ASM_VOLATILE_BINARY32_DOUBLE(add.d)
+          break;
+      case SUBS:
+          ASM_VOLATILE_BINARY32(sub.s)
+          break;
+      case SUBD:
+          ASM_VOLATILE_BINARY32_DOUBLE(sub.d)
+          break;
+      case DIVS:
+          ASM_VOLATILE_BINARY32(div.s)
+          break;
+      default:
+         vassert(0);
+         break;
+   }
+#endif
+   return ret;
+}
+
+/* TODO: Add cases for all fpu instructions because all fpu instructions are
+         change the value of FCSR register. */
+extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs, UInt fs, UInt ft,
+                                                   flt_op inst )
 {
    UInt ret = 0;
 #if defined(__mips__)
 #if defined(VGA_mips32)
    VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
-   UInt *addr    = (UInt *)&guest_state->guest_f0;
-   UInt loFsVal  = addr[fs];
-   UInt hiFsVal  = addr[fs+1];
-   UInt loFtVal  = addr[ft];
-   UInt hiFtVal  = addr[ft+1];
-#define ASM_VOLATILE_UNARY(inst)         ASM_VOLATILE_UNARY32(inst)
-#define ASM_VOLATILE_UNARY_DOUBLE(inst)  ASM_VOLATILE_UNARY32_DOUBLE(inst)
-#define ASM_VOLATILE_BINARY(inst)        ASM_VOLATILE_BINARY32(inst)
-#define ASM_VOLATILE_BINARY_DOUBLE(inst) ASM_VOLATILE_BINARY32_DOUBLE(inst)
 #else
    VexGuestMIPS64State* guest_state = (VexGuestMIPS64State*)gs;
-   ULong *addr = (ULong *)&guest_state->guest_f0;
-   ULong fsVal = addr[fs];
-   ULong ftVal = addr[ft];
-#define ASM_VOLATILE_UNARY(inst)         ASM_VOLATILE_UNARY64(inst)
-#define ASM_VOLATILE_UNARY_DOUBLE(inst)  ASM_VOLATILE_UNARY64(inst)
-#define ASM_VOLATILE_BINARY(inst)        ASM_VOLATILE_BINARY64(inst)
-#define ASM_VOLATILE_BINARY_DOUBLE(inst) ASM_VOLATILE_BINARY64(inst)
 #endif
-   UInt fcsr = guest_state->guest_FCSR;
+   ULong *addr = (ULong *)&guest_state->guest_f0;
+   UInt fcsr   = guest_state->guest_FCSR;
    switch (inst) {
       case ROUNDWD:
-         ASM_VOLATILE_UNARY_DOUBLE(round.w.d)
+         ASM_VOLATILE_UNARY64(round.w.d)
          break;
       case FLOORWS:
-         ASM_VOLATILE_UNARY(floor.w.s)
+         ASM_VOLATILE_UNARY64(floor.w.s)
          break;
       case FLOORWD:
-         ASM_VOLATILE_UNARY_DOUBLE(floor.w.d)
+         ASM_VOLATILE_UNARY64(floor.w.d)
          break;
       case TRUNCWS:
-         ASM_VOLATILE_UNARY(trunc.w.s)
+         ASM_VOLATILE_UNARY64(trunc.w.s)
          break;
       case TRUNCWD:
-         ASM_VOLATILE_UNARY_DOUBLE(trunc.w.d)
+         ASM_VOLATILE_UNARY64(trunc.w.d)
          break;
       case CEILWS:
-         ASM_VOLATILE_UNARY(ceil.w.s)
+         ASM_VOLATILE_UNARY64(ceil.w.s)
          break;
       case CEILWD:
-         ASM_VOLATILE_UNARY_DOUBLE(ceil.w.d)
+         ASM_VOLATILE_UNARY64(ceil.w.d)
          break;
       case CVTDS:
-         ASM_VOLATILE_UNARY(cvt.d.s)
+         ASM_VOLATILE_UNARY64(cvt.d.s)
          break;
       case CVTDW:
-         ASM_VOLATILE_UNARY(cvt.d.w)
+         ASM_VOLATILE_UNARY64(cvt.d.w)
          break;
       case CVTSW:
-         ASM_VOLATILE_UNARY(cvt.s.w)
+         ASM_VOLATILE_UNARY64(cvt.s.w)
          break;
       case CVTSD:
-         ASM_VOLATILE_UNARY_DOUBLE(cvt.s.d)
+         ASM_VOLATILE_UNARY64(cvt.s.d)
          break;
       case CVTWS:
-         ASM_VOLATILE_UNARY(cvt.w.s)
+         ASM_VOLATILE_UNARY64(cvt.w.s)
          break;
       case CVTWD:
-         ASM_VOLATILE_UNARY_DOUBLE(cvt.w.d)
+         ASM_VOLATILE_UNARY64(cvt.w.d)
          break;
       case ROUNDWS:
-         ASM_VOLATILE_UNARY(round.w.s)
+         ASM_VOLATILE_UNARY64(round.w.s)
          break;
 #if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
     || (__mips == 64)
       case CEILLS:
-         ASM_VOLATILE_UNARY(ceil.l.s)
+         ASM_VOLATILE_UNARY64(ceil.l.s)
          break;
       case CEILLD:
-         ASM_VOLATILE_UNARY_DOUBLE(ceil.l.d)
+         ASM_VOLATILE_UNARY64(ceil.l.d)
          break;
       case CVTDL:
-         ASM_VOLATILE_UNARY_DOUBLE(cvt.d.l)
+         ASM_VOLATILE_UNARY64(cvt.d.l)
          break;
       case CVTLS:
-         ASM_VOLATILE_UNARY(cvt.l.s)
+         ASM_VOLATILE_UNARY64(cvt.l.s)
          break;
       case CVTLD:
-         ASM_VOLATILE_UNARY_DOUBLE(cvt.l.d)
+         ASM_VOLATILE_UNARY64(cvt.l.d)
          break;
       case CVTSL:
-         ASM_VOLATILE_UNARY_DOUBLE(cvt.s.l)
+         ASM_VOLATILE_UNARY64(cvt.s.l)
          break;
       case FLOORLS:
-         ASM_VOLATILE_UNARY(floor.l.s)
+         ASM_VOLATILE_UNARY64(floor.l.s)
          break;
       case FLOORLD:
-         ASM_VOLATILE_UNARY_DOUBLE(floor.l.d)
+         ASM_VOLATILE_UNARY64(floor.l.d)
          break;
       case ROUNDLS:
-         ASM_VOLATILE_UNARY(round.l.s)
+         ASM_VOLATILE_UNARY64(round.l.s)
          break;
       case ROUNDLD:
-         ASM_VOLATILE_UNARY_DOUBLE(round.l.d)
+         ASM_VOLATILE_UNARY64(round.l.d)
          break;
       case TRUNCLS:
-         ASM_VOLATILE_UNARY(trunc.l.s)
+         ASM_VOLATILE_UNARY64(trunc.l.s)
          break;
       case TRUNCLD:
-         ASM_VOLATILE_UNARY_DOUBLE(trunc.l.d)
+         ASM_VOLATILE_UNARY64(trunc.l.d)
          break;
 #endif
       case ADDS:
-          ASM_VOLATILE_BINARY(add.s)
+          ASM_VOLATILE_BINARY64(add.s)
           break;
       case ADDD:
-          ASM_VOLATILE_BINARY_DOUBLE(add.d)
+          ASM_VOLATILE_BINARY64(add.d)
           break;
       case SUBS:
-          ASM_VOLATILE_BINARY(sub.s)
+          ASM_VOLATILE_BINARY64(sub.s)
           break;
       case SUBD:
-          ASM_VOLATILE_BINARY_DOUBLE(sub.d)
+          ASM_VOLATILE_BINARY64(sub.d)
           break;
       case DIVS:
-          ASM_VOLATILE_BINARY(div.s)
+          ASM_VOLATILE_BINARY64(div.s)
           break;
       default:
          vassert(0);
diff --git a/priv/guest_mips_toIR.c b/priv/guest_mips_toIR.c
index 9ee65bf..94ec293 100644
--- a/priv/guest_mips_toIR.c
+++ b/priv/guest_mips_toIR.c
@@ -72,6 +72,9 @@
    disInstr_MIPS below. */
 static Bool mode64 = False;
 
+/* CPU has FPU and 32 dbl. prec. FP registers. */
+static Bool fp_mode64 = False;
+
 /* Define 1.0 in single and double precision. */
 #define ONE_SINGLE 0x3F800000
 #define ONE_DOUBLE 0x3FF0000000000000ULL
@@ -541,6 +544,11 @@
                              binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
                  mkU32(0x1)));
 
+#define ILLEGAL_INSTRUCTON \
+   putPC(mkU32(guest_PC_curr_instr + 4)); \
+   dres.jk_StopHere = Ijk_SigILL; \
+   dres.whatNext    = Dis_StopHere;
+
 /*------------------------------------------------------------*/
 /*---                  Field helpers                       ---*/
 /*------------------------------------------------------------*/
@@ -1105,22 +1113,30 @@
 {
    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_4(IRExpr_BBPTR(),
-                                       mkU32(fs),
-                                       mkU32(ft),
-                                       mkU32(inst)));
+   /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
+   if (fp_mode64)
+      d = unsafeIRDirty_1_N(fcsr, 0,
+                            "mips_dirtyhelper_calculate_FCSR_fp64",
+                            &mips_dirtyhelper_calculate_FCSR_fp64,
+                            mkIRExprVec_4(IRExpr_BBPTR(),
+                                          mkU32(fs),
+                                          mkU32(ft),
+                                          mkU32(inst)));
+   else
+      d = unsafeIRDirty_1_N(fcsr, 0,
+                            "mips_dirtyhelper_calculate_FCSR_fp32",
+                            &mips_dirtyhelper_calculate_FCSR_fp32,
+                            mkIRExprVec_4(IRExpr_BBPTR(),
+                                          mkU32(fs),
+                                          mkU32(ft),
+                                          mkU32(inst)));
 
    if (opN == 1) {  /* Unary operation. */
       /* Declare we're reading guest state. */
-      if (!mode64 && !sz32)
-         d->nFxState = 3;
-      else
+      if (sz32 || fp_mode64)
          d->nFxState = 2;
+      else
+         d->nFxState = 3;
       vex_bzero(&d->fxState, sizeof(d->fxState));
 
       d->fxState[0].fx     = Ifx_Read;  /* read */
@@ -1128,22 +1144,19 @@
       d->fxState[0].size   = sizeof(UInt);
       d->fxState[1].fx     = Ifx_Read;  /* read */
       d->fxState[1].offset = floatGuestRegOffset(fs);
-      if (mode64)
-         d->fxState[1].size   = sizeof(ULong);
-      else
-         d->fxState[1].size   = sizeof(UInt);
+      d->fxState[1].size   = sizeof(ULong);
 
-      if (!mode64 && !sz32) {
+      if (!(sz32 || fp_mode64)) {
          d->fxState[2].fx     = Ifx_Read;  /* read */
          d->fxState[2].offset = floatGuestRegOffset(fs+1);
-         d->fxState[2].size   = sizeof(UInt);
+         d->fxState[2].size   = sizeof(ULong);
       }
    } else if (opN == 2) {  /* Binary operation. */
       /* Declare we're reading guest state. */
-      if (!mode64 && !sz32)
-         d->nFxState = 5;
-      else
+      if (sz32 || fp_mode64)
          d->nFxState = 3;
+      else
+         d->nFxState = 5;
       vex_bzero(&d->fxState, sizeof(d->fxState));
 
       d->fxState[0].fx     = Ifx_Read;  /* read */
@@ -1151,22 +1164,18 @@
       d->fxState[0].size   = sizeof(UInt);
       d->fxState[1].fx     = Ifx_Read;  /* read */
       d->fxState[1].offset = floatGuestRegOffset(fs);
+      d->fxState[1].size   = sizeof(ULong);
       d->fxState[2].fx     = Ifx_Read;  /* read */
       d->fxState[2].offset = floatGuestRegOffset(ft);
-      if (mode64) {
-         d->fxState[1].size   = sizeof(ULong);
-         d->fxState[2].size   = sizeof(ULong);
-      } else {
-         d->fxState[1].size   = sizeof(UInt);
-         d->fxState[2].size   = sizeof(UInt);
-      }
-      if (!mode64 && !sz32) {
+      d->fxState[2].size   = sizeof(ULong);
+
+      if (!(sz32 || fp_mode64)) {
          d->fxState[3].fx     = Ifx_Read;  /* read */
          d->fxState[3].offset = floatGuestRegOffset(fs+1);
-         d->fxState[3].size   = sizeof(UInt);
+         d->fxState[3].size   = sizeof(ULong);
          d->fxState[4].fx     = Ifx_Read;  /* read */
          d->fxState[4].offset = floatGuestRegOffset(ft+1);
-         d->fxState[4].size   = sizeof(UInt);
+         d->fxState[4].size   = sizeof(ULong);
       }
    }
 
@@ -1192,6 +1201,12 @@
       stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
 }
 
+static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
+}
+
 static void putLO(IRExpr * e)
 {
    if (mode64) {
@@ -1285,12 +1300,6 @@
    return 0;
 }
 
-static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
-{
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
-}
-
 static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
 {
    vassert(ty == Ity_F32 || ty == Ity_F64);
@@ -1386,21 +1395,21 @@
                                      (UInt) branch_offset), OFFB_PC);
 }
 
-static IRExpr *getFReg(UInt dregNo)
+static IRExpr *getFReg(UInt fregNo)
 {
-   vassert(dregNo < 32);
-   IRType ty = mode64 ? Ity_F64 : Ity_F32;
-   return IRExpr_Get(floatGuestRegOffset(dregNo), ty);
+   vassert(fregNo < 32);
+   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
+   return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
 }
 
 static IRExpr *getDReg(UInt dregNo)
 {
-   if (mode64) {
-      vassert(dregNo < 32);
-      IRType ty = Ity_F64;
-      return IRExpr_Get(floatGuestRegOffset(dregNo), ty);
+   vassert(dregNo < 32);
+   if (fp_mode64) {
+      return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
    } else {
-      vassert(dregNo < 32);
+      /* Read a floating point register pair and combine their contents into a
+         64-bit value */
       IRTemp t0 = newTemp(Ity_F32);
       IRTemp t1 = newTemp(Ity_F32);
       IRTemp t2 = newTemp(Ity_F64);
@@ -1423,14 +1432,14 @@
 static void putFReg(UInt dregNo, IRExpr * e)
 {
    vassert(dregNo < 32);
-   IRType ty = mode64 ? Ity_F64 : Ity_F32;
+   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
    vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
    stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
 }
 
 static void putDReg(UInt dregNo, IRExpr * e)
 {
-   if (mode64) {
+   if (fp_mode64) {
       vassert(dregNo < 32);
       IRType ty = Ity_F64;
       vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
@@ -1725,7 +1734,7 @@
       switch (fmt) {
          case 0x10: {  /* C.cond.S */
             DIP("C.%s.S %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
-            if (mode64) {
+            if (fp_mode64) {
                t0 = newTemp(Ity_I32);
                t1 = newTemp(Ity_I32);
                t2 = newTemp(Ity_I32);
@@ -1740,7 +1749,8 @@
                                  getFReg(ft))));
 
                assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
-               putHI(mkWidenFrom32(Ity_I64, mkexpr(ccIR), True));
+               putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
+                                   mkexpr(ccIR), True));
                /* Map compare result from IR to MIPS
                   FP cmp result | MIPS | IR
                   --------------------------
@@ -1757,7 +1767,8 @@
                               binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
                               binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
                               mkU32(1))))));
-               putLO(mkWidenFrom32(Ity_I64, mkexpr(ccMIPS), True));
+               putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
+                                   mkexpr(ccMIPS), True));
 
                /* UN */
                assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
@@ -11829,7 +11840,7 @@
    trap_code = get_code(cins);
    function = get_function(cins);
    IRType ty = mode64 ? Ity_I64 : Ity_I32;
-   IRType tyF = mode64 ? Ity_F64 : Ity_F32;
+   IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
 
    ac = get_acNo(cins);
 
@@ -11862,110 +11873,119 @@
       lastn = mkexpr(t0);
       break;
 
-   case 0x11:     /* COP1 */
-      {
-         UInt bc1_cc = get_bc1_cc(cins);
-         if (0x08 == fmt) {
-            switch (fmt) {
-            case 0x08:  /* BC */
-               {
-                  DIP("tf: %d, nd: %d", tf, nd);
-                  /* FcConditionalCode(bc1_cc) */
-                  t1 = newTemp(Ity_I1);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I1);
-
-                  assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
-                  assign(t2, IRExpr_ITE(mkexpr(t1),
-                                        binop(Iop_And32,
-                                              binop(Iop_Shr32, getFCSR(),
-                                                    mkU8(23)),
-                                              mkU32(0x1)),
-                                        binop(Iop_And32,
-                                              binop(Iop_Shr32, getFCSR(),
-                                                    mkU8(24 + bc1_cc)),
-                                              mkU32(0x1))
-                                        ));
-
-                  if (tf == 1 && nd == 0) {
-                     /* branch on true */
-                     DIP("bc1t %d, %d", bc1_cc, imm);
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
-                     dis_branch(False, mkexpr(t3), imm, &bstmt);
-                     break;
-                  } else if (tf == 0 && nd == 0) {
-                     /* branch on false */
-                     DIP("bc1f %d, %d", bc1_cc, imm);
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
-                     dis_branch(False, mkexpr(t3), imm, &bstmt);
-                     break;
-                  } else if (nd == 1 && tf == 0) {
-                     DIP("bc1fl %d, %d", bc1_cc, imm);
-                     lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
-                                               mkU32(0x0)), imm);
-                     break;
-                  } else if (nd == 1 && tf == 1) {
-                     DIP("bc1tl %d, %d", bc1_cc, imm);
-                     lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
-                                               mkU32(0x0)), imm);
-                     break;
-                  } else
-                     goto decode_failure;
-               }
-
-            default:
-               goto decode_failure;
-            }
+   case 0x11: {  /* COP1 */
+      if (fmt == 0x3 && fd == 0 && function == 0) {  /* MFHC1 */
+         DIP("mfhc1 r%d, f%d", rt, fs);
+         if (fp_mode64) {
+            t0 = newTemp(Ity_I64);
+            t1 = newTemp(Ity_I32);
+            assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
+            assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
+            putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
          } else {
-            switch (function) {
+            ILLEGAL_INSTRUCTON;
+         }
+         break;
+      } else if (fmt == 0x7 && fd == 0 && function == 0) {  /* MTHC1 */
+         DIP("mthc1 r%d, f%d", rt, fs);
+         if (fp_mode64) {
+            t0 = newTemp(Ity_I64);
+            assign(t0, binop(Iop_32HLto64, getIReg(rt),
+                             unop(Iop_ReinterpF32asI32,
+                                  getLoFromF64(Ity_F64 /* 32FPR mode. */,
+                                               getDReg(fs)))));
+            putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+         } else {
+            ILLEGAL_INSTRUCTON;
+         }
+         break;
+      } else if (fmt == 0x8) {  /* BC */
+         /* FcConditionalCode(bc1_cc) */
+         UInt bc1_cc = get_bc1_cc(cins);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
 
-            case 0x4:  /* SQRT.fmt */
-               {
-                  switch (fmt) {
-                  case 0x10:  /* S */
-                     {
-                        IRExpr *rm = get_IR_roundingmode();
-                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
-                                    getLoFromF64(tyF, getFReg(fs)))));
-                     }
+         assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
+         assign(t2, IRExpr_ITE(mkexpr(t1),
+                               binop(Iop_And32,
+                                     binop(Iop_Shr32, getFCSR(), mkU8(23)),
+                                     mkU32(0x1)),
+                               binop(Iop_And32,
+                                     binop(Iop_Shr32, getFCSR(),
+                                           mkU8(24 + bc1_cc)),
+                                     mkU32(0x1))));
+
+         if (tf == 1 && nd == 0) {
+            /* branch on true */
+            DIP("bc1t %d, %d", bc1_cc, imm);
+            assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+            dis_branch(False, mkexpr(t3), imm, &bstmt);
+            break;
+         } else if (tf == 0 && nd == 0) {
+            /* branch on false */
+            DIP("bc1f %d, %d", bc1_cc, imm);
+            assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+            dis_branch(False, mkexpr(t3), imm, &bstmt);
+            break;
+         } else if (nd == 1 && tf == 0) {
+            DIP("bc1fl %d, %d", bc1_cc, imm);
+            lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
+                                            mkU32(0x0)), imm);
+            break;
+         } else if (nd == 1 && tf == 1) {
+            DIP("bc1tl %d, %d", bc1_cc, imm);
+            lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
+                                            mkU32(0x0)), imm);
+            break;
+         } else
+            goto decode_failure;
+      } else {
+         switch (function) {
+            case 0x4: {  /* SQRT.fmt */
+               switch (fmt) {
+                  case 0x10: {  /* S */
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
+                                 getLoFromF64(tyF, getFReg(fs)))));
                      break;
-                  case 0x11:  /* D */
-                     {
-                        IRExpr *rm = get_IR_roundingmode();
-                        putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
-                     }
+                  }
+                  case 0x11: {  /* D */
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
                      break;
                   }
+                  default:
+                     goto decode_failure;
+                  }
                }
                break;
             case 0x5:  /* abs.fmt */
                switch (fmt) {
-               case 0x10:  /* S */
-                  DIP("abs.s f%d, f%d", fd, fs);
-                  putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
-                              getLoFromF64(tyF, getFReg(fs)))));
-                  break;
-               case 0x11:  /* D  */
-                  DIP("abs.d f%d, f%d", fd, fs);
-                  putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
-                  break;
-               default:
-                  goto decode_failure;
+                  case 0x10:  /* S */
+                     DIP("abs.s f%d, f%d", fd, fs);
+                     putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
+                                 getLoFromF64(tyF, getFReg(fs)))));
+                     break;
+                  case 0x11:  /* D  */
+                     DIP("abs.d f%d, f%d", fd, fs);
+                     putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
+                     break;
+                  default:
+                     goto decode_failure;
                }
                break;  /* case 0x5 */
 
             case 0x02:  /* MUL.fmt */
                switch (fmt) {
-               case 0x11:  /* D */
-                  {
+                  case 0x11: {  /* D */
                      DIP("mul.d f%d, f%d, f%d", fd, fs, ft);
                      IRExpr *rm = get_IR_roundingmode();
                      putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
                                        getDReg(ft)));
                      break;
                   }
-               case 0x10:  /* S */
-                  {
+                  case 0x10: {  /* S */
                      DIP("mul.s f%d, f%d, f%d", fd, fs, ft);
                      IRExpr *rm = get_IR_roundingmode();
                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
@@ -11973,23 +11993,21 @@
                                  getLoFromF64(tyF, getFReg(ft)))));
                      break;
                   }
-               default:
-                  goto decode_failure;
+                  default:
+                     goto decode_failure;
                }
                break;  /* MUL.fmt */
 
             case 0x03:  /* DIV.fmt */
                switch (fmt) {
-               case 0x11:  /* D */
-                  {
+                  case 0x11: {  /* D */
                      DIP("div.d f%d, f%d, f%d", fd, fs, ft);
                      IRExpr *rm = get_IR_roundingmode();
                      putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
                                  getDReg(ft)));
                      break;
                   }
-               case 0x10:  /* S */
-                  {
+                  case 0x10: {  /* S */
                      DIP("div.s f%d, f%d, f%d", fd, fs, ft);
                      calculateFCSR(fs, ft, DIVS, False, 2);
                      IRExpr *rm = get_IR_roundingmode();
@@ -11998,8 +12016,8 @@
                                  getLoFromF64(tyF, getFReg(ft)))));
                      break;
                   }
-               default:
-                  goto decode_failure;
+                  default:
+                     goto decode_failure;
                }
                break;  /* DIV.fmt */
 
@@ -12031,8 +12049,8 @@
                switch (fmt) {
                   case 0x11:  /* D */
                      DIP("mov.d f%d, f%d", fd, fs);
-                     if (mode64) {
-                        putFReg(fd, getFReg(fs));
+                     if (fp_mode64) {
+                        putDReg(fd, getDReg(fs));
                      } else {
                         putFReg(fd, getFReg(fs));
                         putFReg(fd + 1, getFReg(fs + 1));
@@ -12067,19 +12085,27 @@
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("round.l.s f%d, f%d", fd, fs);
-                     calculateFCSR(fs, 0, ROUNDLS, True, 1);
-                     t0 = newTemp(Ity_I64);
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, ROUNDLS, True, 1);
+                        t0 = newTemp(Ity_I64);
 
-                     assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
-                                getLoFromF64(Ity_F64, getFReg(fs))));
+                        assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
+                                         getLoFromF64(Ity_F64, getFReg(fs))));
 
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                  break;
+                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
+                     break;
                   case 0x11:  /* D */
                      DIP("round.l.d f%d, f%d", fd, fs);
-                     calculateFCSR(fs, 0, ROUNDLD, False, 1);
-                     putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0),
-                                       getFReg(fs)));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, ROUNDLD, False, 1);
+                        putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0),
+                                          getDReg(fs)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
                   default:
                     goto decode_failure;
@@ -12091,18 +12117,26 @@
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("trunc.l.s f%d, f%d", fd, fs);
-                     calculateFCSR(fs, 0, TRUNCLS, True, 1);
-                     t0 = newTemp(Ity_I64);
-                     assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
-                                      getLoFromF64(Ity_F64, getFReg(fs))));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, TRUNCLS, True, 1);
+                        t0 = newTemp(Ity_I64);
+                        assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
+                                         getLoFromF64(Ity_F64, getFReg(fs))));
 
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
                   case 0x11:  /* D */
                      DIP("trunc.l.d f%d, f%d", fd, fs);
-                     calculateFCSR(fs, 0, TRUNCLD, False, 1);
-                     putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3),
-                                       getFReg(fs)));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, TRUNCLD, False, 1);
+                        putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3),
+                                          getDReg(fs)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
                   default:
                      goto decode_failure;
@@ -12139,7 +12173,6 @@
                switch (fmt) {
                case 0x10:  /* S */
                   DIP("movn.s f%d, f%d, r%d", fd, fs, rt);
-
                   t1 = newTemp(Ity_F64);
                   t2 = newTemp(Ity_F64);
                   t3 = newTemp(Ity_I1);
@@ -12149,13 +12182,19 @@
                      assign(t2, getFReg(fd));
                      assign(t3, binop(Iop_CmpNE64, mkU64(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)));
+                     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 (mode64) {
+                  if (fp_mode64) {
                      IRTemp f = newTemp(Ity_F64);
                      IRTemp fd_hi = newTemp(Ity_I32);
                      t5 = newTemp(Ity_I64);
@@ -12163,7 +12202,7 @@
                      assign(fd_hi, unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
                                         mkexpr(f))));
 
-                     assign(t5, mkWidenFrom32(ty, unop(Iop_64to32,
+                     assign(t5, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
                                 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
 
                      putFReg(fd, unop (Iop_ReinterpI64asF64, mkexpr(t5)));
@@ -12198,10 +12237,13 @@
                   t2 = newTemp(Ity_F64);
                   t3 = newTemp(Ity_I1);
                   t4 = newTemp(Ity_F64);
-                  if (mode64) {
+                  if (fp_mode64) {
                      assign(t1, getFReg(fs));
                      assign(t2, getFReg(fd));
-                     assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+                     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)));
@@ -12209,14 +12251,14 @@
                   }
                   assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2)));
 
-                 if (mode64) {
+                 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(ty, unop(Iop_64to32,
+                     assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
                                 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
 
                      putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
@@ -12279,7 +12321,7 @@
                      t6 = newTemp(Ity_F64);
                      t7 = newTemp(Ity_I64);
 
-                     if (mode64) {
+                     if (fp_mode64) {
                         assign(t5, getFReg(fs));
                         assign(t6, getFReg(fd));
                      } else {
@@ -12303,13 +12345,13 @@
                      assign(t4, IRExpr_ITE(mkexpr(t3),
                                            mkexpr(t5), mkexpr(t6)));
 
-                     if (mode64) {
+                     if (fp_mode64) {
                         IRTemp f = newTemp(Ity_F64);
                         IRTemp fd_hi = newTemp(Ity_I32);
                         assign(f, getFReg(fd));
                         assign(fd_hi, unop(Iop_64HIto32,
                                       unop(Iop_ReinterpF64asI64, mkexpr(f))));
-                        assign(t7, mkWidenFrom32(ty, unop(Iop_64to32,
+                        assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
                                       unop(Iop_ReinterpF64asI64, mkexpr(t4))),
                                       True));
 
@@ -12359,7 +12401,7 @@
                      t5 = newTemp(Ity_F64);
                      t6 = newTemp(Ity_F64);
 
-                     if (mode64) {
+                     if (fp_mode64) {
                         assign(t5, getFReg(fs));
                         assign(t6, getFReg(fd));
                      } else {
@@ -12383,14 +12425,14 @@
                      assign(t4, IRExpr_ITE(mkexpr(t3),
                                            mkexpr(t5), mkexpr(t6)));
 
-                     if (mode64) {
+                     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(ty, unop(Iop_64to32,
+                        assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
                                    unop(Iop_ReinterpF64asI64, mkexpr(t4))),
                                    True));
 
@@ -12427,10 +12469,10 @@
 
                case 0x4:  /* MTC1 (Move Word to Floating Point) */
                   DIP("mtc1 r%d, f%d", rt, fs);
-                  if (mode64) {
+                  if (fp_mode64) {
                      t0 = newTemp(Ity_I32);
                      t1 = newTemp(Ity_F32);
-                     assign(t0, unop(Iop_64to32, getIReg(rt)));
+                     assign(t0, mkNarrowTo32(ty, getIReg(rt)));
                      assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
 
                      putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
@@ -12446,7 +12488,7 @@
 
                case 0x0:  /* MFC1 */
                   DIP("mfc1 r%d, f%d", rt, fs);
-                  if (mode64) {
+                  if (fp_mode64) {
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I32);
                      assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
@@ -12570,7 +12612,7 @@
                   case 0x10:  /* S */
                      DIP("cvt.d.s f%d, f%d", fd, fs);
                      calculateFCSR(fs, 0, CVTDS, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12590,7 +12632,7 @@
                   case 0x14:
                      DIP("cvt.d.w %d, %d", fd, fs);
                      calculateFCSR(fs, 0, CVTDW, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12609,7 +12651,7 @@
                      }
 
                   case 0x15: {  /* L */
-                     if (mode64) {
+                     if (fp_mode64) {
                         DIP("cvt.d.l %d, %d", fd, fs);
                         calculateFCSR(fs, 0, CVTDL, False, 1);
                         t0 = newTemp(Ity_I64);
@@ -12631,7 +12673,7 @@
                   case 0x14:  /* W */
                      DIP("cvt.s.w %d, %d", fd, fs);
                      calculateFCSR(fs, 0, CVTSW, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12653,14 +12695,10 @@
                   case 0x11:  /* D */
                      DIP("cvt.s.d %d, %d", fd, fs);
                      calculateFCSR(fs, 0, CVTSD, False, 1);
-                     if (mode64) {
-                        t0 = newTemp(Ity_F32);
-                        assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                         getFReg(fs)));
-                        putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
-                     } else
-                        putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                          getDReg(fs)));
+                     t0 = newTemp(Ity_F32);
+                     assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                      getDReg(fs)));
+                     putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
                      break;
 
                   case 0x15:  /* L */
@@ -12683,33 +12721,23 @@
                case 0x10:  /* S */
                   DIP("cvt.w.s %d, %d", fd, fs);
                   calculateFCSR(fs, 0, CVTWS, True, 1);
-                  if (mode64) {
-                     putFReg(fd, mkWidenFromF32(tyF, binop(Iop_RoundF32toInt,
-                             get_IR_roundingmode(), getLoFromF64(tyF,
-                                                                getFReg(fs)))));
-                  } else
-                     putFReg(fd, binop(Iop_RoundF32toInt, get_IR_roundingmode(),
-                                       getFReg(fs)));
+                  putFReg(fd,
+                          mkWidenFromF32(tyF,
+                                         binop(Iop_RoundF32toInt,
+                                               get_IR_roundingmode(),
+                                               getLoFromF64(tyF, getFReg(fs))))
+                         );
                   break;
 
                case 0x11:
                   DIP("cvt.w.d %d, %d", fd, fs);
                   calculateFCSR(fs, 0, CVTWD, False, 1);
-                  if (mode64) {
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_F32);
-                     assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
-                                      getFReg(fs)));
-                     assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                     putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
-                  } else {
-                     t0 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
-                                      getDReg(fs)));
-
-                     putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                  }
+                  t0 = newTemp(Ity_I32);
+                  t1 = newTemp(Ity_F32);
+                  assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
+                                   getDReg(fs)));
+                  assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
                   break;
 
                default:
@@ -12722,20 +12750,28 @@
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("cvt.l.s %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, CVTLS, True, 1);
-                     t0 = newTemp(Ity_I64);
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, CVTLS, True, 1);
+                        t0 = newTemp(Ity_I64);
 
-                     assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
-                                      getLoFromF64(Ity_F64, getFReg(fs))));
+                        assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
+                                         getLoFromF64(tyF, getFReg(fs))));
 
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
 
                   case 0x11: {  /* D */
                      DIP("cvt.l.d %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, CVTLD, False, 1);
-                     putFReg(fd, binop(Iop_RoundF64toInt,
-                             get_IR_roundingmode(), getFReg(fs)));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, CVTLD, False, 1);
+                        putDReg(fd, binop(Iop_RoundF64toInt,
+                                get_IR_roundingmode(), getDReg(fs)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
                   }
 
@@ -12748,20 +12784,28 @@
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("floor.l.s %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, FLOORLS, True, 1);
-                     t0 = newTemp(Ity_I64);
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, FLOORLS, True, 1);
+                        t0 = newTemp(Ity_I64);
 
-                     assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
-                                      getLoFromF64(Ity_F64, getFReg(fs))));
+                        assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
+                                         getLoFromF64(tyF, getFReg(fs))));
 
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
 
                   case 0x11:  /* D */
                      DIP("floor.l.d %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, FLOORLD, False, 1);
-                     putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1),
-                                       getFReg(fs)));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, FLOORLD, False, 1);
+                        putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1),
+                                          getDReg(fs)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
                   default:
                      goto decode_failure;
@@ -12773,7 +12817,7 @@
                   case 0x10:  /* S */
                      DIP("round.w.s f%d, f%d", fd, fs);
                      calculateFCSR(fs, 0, ROUNDWS, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12797,7 +12841,7 @@
                   case 0x11:  /* D */
                      DIP("round.w.d f%d, f%d", fd, fs);
                      calculateFCSR(fs, 0, ROUNDWD, False, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
                                          getDReg(fs)));
@@ -12823,7 +12867,7 @@
                   case 0x10:  /* S */
                      DIP("floor.w.s f%d, f%d", fd, fs);
                      calculateFCSR(fs, 0, FLOORWS, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12847,7 +12891,7 @@
                   case 0x11:  /* D */
                      DIP("floor.w.d f%d, f%d", fd, fs);
                      calculateFCSR(fs, 0, FLOORWD, False, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
                                          getDReg(fs)));
@@ -12874,7 +12918,7 @@
                   case 0x10:  /* S */
                      DIP("trunc.w.s %d, %d", fd, fs);
                      calculateFCSR(fs, 0, TRUNCWS, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12897,7 +12941,7 @@
                   case 0x11:  /* D */
                      DIP("trunc.w.d %d, %d", fd, fs);
                      calculateFCSR(fs, 0, TRUNCWD, False, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I32);
 
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
@@ -12925,7 +12969,7 @@
                   case 0x10:  /* S */
                      DIP("ceil.w.s %d, %d", fd, fs);
                      calculateFCSR(fs, 0, CEILWS, True, 1);
-                     if (mode64) {
+                     if (fp_mode64) {
                         t0 = newTemp(Ity_I64);
                         t1 = newTemp(Ity_I32);
                         t3 = newTemp(Ity_F32);
@@ -12949,7 +12993,7 @@
                   case 0x11:  /* D */
                      DIP("ceil.w.d %d, %d", fd, fs);
                      calculateFCSR(fs, 0, CEILWD, False, 1);
-                     if (!mode64) {
+                     if (!fp_mode64) {
                         t0 = newTemp(Ity_I32);
                         assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
                                          getDReg(fs)));
@@ -12972,20 +13016,28 @@
                switch (fmt) {
                   case 0x10:  /* S */
                      DIP("ceil.l.s %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, CEILLS, True, 1);
-                     t0 = newTemp(Ity_I64);
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, CEILLS, True, 1);
+                        t0 = newTemp(Ity_I64);
 
-                     assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
-                                getLoFromF64(Ity_F64, getFReg(fs))));
+                        assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
+                                   getLoFromF64(tyF, getFReg(fs))));
 
-                     putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
 
                   case 0x11:  /* D */
                      DIP("ceil.l.d %d, %d", fd, fs);
-                     calculateFCSR(fs, 0, CEILLD, False, 1);
-                     putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2),
-                                       getFReg(fs)));
+                     if (fp_mode64) {
+                        calculateFCSR(fs, 0, CEILLD, False, 1);
+                        putFReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2),
+                                          getFReg(fs)));
+                     } else {
+                        ILLEGAL_INSTRUCTON;
+                     }
                      break;
 
                   default:
@@ -13061,17 +13113,24 @@
    case 0x31:  /* LWC1 */
       /* Load Word to Floating Point - LWC1 (MIPS32) */
       DIP("lwc1 f%d, %d(r%d)", ft, imm, rs);
-      if (mode64) {
-         t0 = newTemp(Ity_I64);
+      if (fp_mode64) {
          t1 = newTemp(Ity_F32);
          t2 = newTemp(Ity_I64);
-         /* new LO */
-         assign(t0, binop(Iop_Add64, getIReg(rs),
-                          mkU64(extend_s_16to64(imm))));
+         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(t2, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
-                                           mkexpr(t1)), True));
-         putFReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
+         assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+                                                mkexpr(t1)), True));
+         putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
       } else {
          t0 = newTemp(Ity_I32);
          assign(t0, binop(Iop_Add32, getIReg(rs),
@@ -13082,7 +13141,7 @@
 
    case 0x39:  /* SWC1 */
       DIP("swc1 f%d, %d(r%d)", ft, imm, rs);
-      if (mode64) {
+      if (fp_mode64) {
          t0 = newTemp(Ity_I64);
          t2 = newTemp(Ity_I32);
          LOAD_STORE_PATTERN;
@@ -13101,22 +13160,16 @@
 
    case 0x35:
       /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         putFReg(ft, load(Ity_F64, mkexpr(t1)));
-      else
-         putDReg(ft, load(Ity_F64, mkexpr(t1)));
       DIP("ldc1 f%d, %d(%d)", rt, imm, rs);
+      LOAD_STORE_PATTERN;
+      putDReg(ft, load(Ity_F64, mkexpr(t1)));
       break;
 
    case 0x3D:
       /* Store Doubleword from Floating Point - SDC1 */
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         store(mkexpr(t1), getFReg(ft));
-      else
-         store(mkexpr(t1), getDReg(ft));
       DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
+      LOAD_STORE_PATTERN;
+      store(mkexpr(t1), getDReg(ft));
       break;
 
    case 0x23:  /* LW */
@@ -13175,19 +13228,20 @@
       case 0x0: {  /* LWXC1 */
          /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
          DIP("lwxc1 f%d, r%d(r%d)", fd, rt, rs);
-         if (mode64) {
+         if (fp_mode64) {
             t0 = newTemp(Ity_I64);
             t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I64);
             t3 = newTemp(Ity_F32);
             t4 = newTemp(Ity_I64);
 
+            t2 = newTemp(ty);
             /* new LO */
-            assign(t2, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
+            assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                             getIReg(rt)));
             assign(t3, load(Ity_F32, mkexpr(t2)));
 
-            assign(t4, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
-                                              mkexpr(t3)), True));
+            assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+                                                   mkexpr(t3)), True));
 
             putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
          } else {
@@ -13201,10 +13255,11 @@
       case 0x1: {  /* LDXC1 */
          /* Load Doubleword  Indexed to Floating Point
             LDXC1 (MIPS32r2 and MIPS64) */
-         if (mode64) {
+         if (fp_mode64) {
             DIP("ldxc1 f%d, r%d(r%d)", fd, rt, rs);
-            t0 = newTemp(Ity_I64);
-            assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
+            t0 = newTemp(ty);
+            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                             getIReg(rt)));
             putFReg(fd, load(Ity_F64, mkexpr(t0)));
             break;
          } else {
@@ -13238,10 +13293,10 @@
 
       case 0x8: {  /* Store Word Indexed from Floating Point - SWXC1 */
          DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs);
-         if (mode64) {
-            t0 = newTemp(Ity_I64);
-            assign(t0, binop(Iop_Add64, 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 {
@@ -13254,9 +13309,10 @@
       }
       case 0x9: {  /* Store Doubleword Indexed from Floating Point - SDXC1 */
          DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
-         if (mode64) {
-            t0 = newTemp(Ity_I64);
-            assign(t0, binop(Iop_Add64, 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), getFReg(fs));
          } else {
             t0 = newTemp(Ity_I32);
@@ -16693,8 +16749,8 @@
 
    decode_failure_dsp:
       vex_printf("Error occured while trying to decode MIPS32 DSP "
-                  "instruction.\nYour platform probably doesn't support "
-                  "MIPS32 DSP ASE.\n");
+                 "instruction.\nYour platform probably doesn't support "
+                 "MIPS32 DSP ASE.\n");
    decode_failure:
       /* All decode failures end up here. */
       if (sigill_diag)
@@ -16797,7 +16853,6 @@
 
 /* Disassemble a single instruction into IR.  The instruction
    is located in host memory at &guest_code[delta]. */
-
 DisResult disInstr_MIPS( IRSB*        irsb_IN,
                          Bool         (*resteerOkFn) ( void *, Addr64 ),
                          Bool         resteerCisOk,
@@ -16816,6 +16871,10 @@
    vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64);
 
    mode64 = guest_arch != VexArchMIPS32;
+#if (__mips_fpr==64)
+   fp_mode64 = ((VEX_MIPS_REV(archinfo->hwcaps) == VEX_PRID_CPU_32FPR)
+                || guest_arch == VexArchMIPS64);
+#endif
 
    guest_code = guest_code_IN;
    irsb = irsb_IN;
diff --git a/priv/host_mips_defs.c b/priv/host_mips_defs.c
index 1addd04..e708434 100644
--- a/priv/host_mips_defs.c
+++ b/priv/host_mips_defs.c
@@ -37,7 +37,7 @@
 #include "host_mips_defs.h"
 
 /* guest_COND offset. */
-#define COND_OFFSET(__mode64) (__mode64 ? 612 : 316)
+#define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
 
 /* Register number for guest state pointer in host code. */
 #define GuestSP 23
@@ -81,7 +81,7 @@
 
    /* But specific for real regs. */
    vassert(hregClass(reg) == HRcInt32 || hregClass(reg) == HRcInt64 ||
-      hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64);
+           hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64);
 
    /* But specific for real regs. */
    switch (hregClass(reg)) {
@@ -91,7 +91,6 @@
          vex_printf("%s", ireg32_names[r]);
          return;
       case HRcInt64:
-         vassert(mode64);
          r = hregNumber (reg);
          vassert (r >= 0 && r < 32);
          vex_printf ("%s", ireg32_names[r]);
@@ -773,6 +772,12 @@
       case Mfp_CVTWD:
          ret = "cvt.w.d";
          break;
+      case Mfp_CVTLD:
+         ret = "cvt.l.d";
+         break;
+      case Mfp_CVTLS:
+         ret = "cvt.l.s";
+         break;
       case Mfp_TRUWD:
          ret = "trunc.w.d";
          break;
@@ -801,6 +806,7 @@
          ret = "C.cond.d";
          break;
       default:
+         vex_printf("Unknown op: %d", op);
          vpanic("showMIPSFpOp");
          break;
    }
@@ -1864,7 +1870,7 @@
          return;
       }
       case Min_FpGpMove: {
-         vex_printf("%s", showMIPSFpGpMoveOp(i->Min.FpGpMove.op));
+         vex_printf("%s ", showMIPSFpGpMoveOp(i->Min.FpGpMove.op));
          ppHRegMIPS(i->Min.FpGpMove.dst, mode64);
          vex_printf(", ");
          ppHRegMIPS(i->Min.FpGpMove.src, mode64);
@@ -2380,7 +2386,6 @@
 static UChar fregNo(HReg r, Bool mode64)
 {
    UInt n;
-   vassert(hregClass(r) == (mode64 ? HRcFlt64 : HRcFlt32));
    vassert(!hregIsVirtual(r));
    n = hregNumber(r);
    vassert(n <= 31);
@@ -2390,7 +2395,6 @@
 static UChar dregNo(HReg r)
 {
    UInt n;
-   vassert(hregClass(r) == HRcFlt64);
    vassert(!hregIsVirtual(r));
    n = hregNumber(r);
    vassert(n <= 31);
@@ -3457,6 +3461,7 @@
             case Ijk_NoDecode:      trcval = VEX_TRC_JMP_NODECODE;      break;
             case Ijk_TInval:        trcval = VEX_TRC_JMP_TINVAL;        break;
             case Ijk_NoRedir:       trcval = VEX_TRC_JMP_NOREDIR;       break;
+            case Ijk_SigILL:        trcval = VEX_TRC_JMP_SIGILL;        break;
             case Ijk_SigTRAP:       trcval = VEX_TRC_JMP_SIGTRAP;       break;
             /* case Ijk_SigSEGV:   trcval = VEX_TRC_JMP_SIGSEGV;       break; */
             case Ijk_SigBUS:        trcval = VEX_TRC_JMP_SIGBUS;        break;
@@ -3886,8 +3891,13 @@
                p = mkFormR(p, 0x11, 0x15, 0, fr_src, fr_dst, 0x20);
                break;
             case Mfp_CVTLS:
-               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
-               fr_src = dregNo(i->Min.FpConvert.src);
+               if (mode64) {
+                  fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+                  fr_src = dregNo(i->Min.FpConvert.src);
+               } else {
+                  fr_dst = dregNo(i->Min.FpConvert.dst);
+                  fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               }
                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x25);
                break;
             case Mfp_CVTLD:
diff --git a/priv/host_mips_isel.c b/priv/host_mips_isel.c
index 346e411..088b808 100644
--- a/priv/host_mips_isel.c
+++ b/priv/host_mips_isel.c
@@ -47,12 +47,14 @@
    ZERO0       Reserved
    GPR12:22    Allocateable
    23          GuestStatePointer
-   23          Allocateable
    SP          StackFramePointer
    RA          LinkRegister */
 
 static Bool mode64 = False;
 
+/* Host CPU has FPU and 32 dbl. prec. FP registers. */
+static Bool fp_mode64 = False;
+
 /* GPR register class for mips32/64 */
 #define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
 
@@ -60,7 +62,7 @@
 #define HRcFPR(__mode64) (__mode64 ? HRcFlt64 : HRcFlt32)
 
 /* guest_COND offset */
-#define COND_OFFSET(__mode64) (__mode64 ? 612 : 316)
+#define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
 
 /*---------------------------------------------------------*/
 /*--- ISelEnv                                           ---*/
@@ -117,6 +119,7 @@
 
       UInt         hwcaps;
       Bool         mode64;
+      Bool         fp_mode64;
 
       Bool         chainingAllowed;
       Addr64       max_ga;
@@ -180,7 +183,7 @@
 
 static HReg newVRegF(ISelEnv * env)
 {
-   HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->mode64),
+   HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->fp_mode64),
                      True /*virtual reg */ );
    env->vreg_ctr++;
    return reg;
@@ -230,13 +233,13 @@
 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
 
-/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an immediate in
-   the range 1 .. 31 inclusive.  Used for doing shift amounts. */
+/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
+   immediate in the range 1 .. 31 inclusive.  Used for doing shift amounts. */
 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
 
-/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an immediate in
-   the range 1 .. 63 inclusive.  Used for doing shift amounts. */
+/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
+   immediate in the range 1 .. 63 inclusive.  Used for doing shift amounts. */
 static MIPSRH *iselWordExpr_RH6u_wrk(ISelEnv * env, IRExpr * e);
 static MIPSRH *iselWordExpr_RH6u(ISelEnv * env, IRExpr * e);
 
@@ -2754,6 +2757,44 @@
             return;
          }
 
+         case Iop_F32toI64S: {
+            HReg tmpD = newVRegD(env);
+            HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
+            HReg tLo  = newVRegI(env);
+            HReg tHi  = newVRegI(env);
+            MIPSAMode *am_addr;
+
+            /* CVTLS tmpD, valF */
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
+            set_MIPS_rounding_default(env);
+
+            sub_from_sp(env, 16);  /* Move SP down 16 bytes */
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            /* store as F64 */
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
+                                           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);
+
+            *rHi = tHi;
+            *rLo = tLo;
+
+            return;
+         }
+
          default:
             break;
       }
@@ -2936,33 +2977,38 @@
 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
 {
    IRType ty = typeOfIRExpr(env->type_env, e);
-   vassert(ty == Ity_F32 || (ty == Ity_F64 && mode64));
+   vassert(ty == Ity_F32 || (ty == Ity_F64 && fp_mode64));
 
    if (e->tag == Iex_RdTmp) {
       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    }
 
    if (e->tag == Iex_Load) {
-      MIPSAMode *am_addr;
-      HReg r_dst = newVRegF(env);
       vassert(e->Iex.Load.ty == Ity_F32
-             || (e->Iex.Load.ty == Ity_F64 && mode64));
-      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
-      if (mode64 && e->Iex.Load.ty == Ity_F64)
+              || (e->Iex.Load.ty == Ity_F64 && fp_mode64));
+      HReg r_dst;
+      MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
+      if (e->Iex.Load.ty == Ity_F64) {
+         r_dst = newVRegD(env);
          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
-      else
+      } else {
+         r_dst = newVRegF(env);
          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
+      }
       return r_dst;
    }
 
    if (e->tag == Iex_Get) {
-      HReg r_dst = newVRegF(env);
       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
                                         GuestStatePointer(mode64));
-      if (mode64)
+      HReg r_dst;
+      if (e->Iex.Load.ty == Ity_F64) {
+         r_dst = newVRegD(env);
          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
-      else
+      } else {
+         r_dst = newVRegF(env);
          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
+      }
       return r_dst;
    }
 
@@ -2979,7 +3025,7 @@
          return r_dst;
       }
       case Iop_F32toF64: {
-         vassert(mode64);
+         vassert(fp_mode64);
          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
          HReg dst = newVRegD(env);
 
@@ -2987,24 +3033,29 @@
          return dst;
       }
       case Iop_ReinterpI64asF64: {
-         vassert(mode64);
-         HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
-         HReg r_dst = newVRegF(env);
-
-         /* Move Doubleword to Floating Point
-            dmtc1 r_dst, fr_src */
-         addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
-
+         HReg r_dst;
+         if (mode64) {
+            HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            r_dst = newVRegF(env);
+            /* Move Doubleword to Floating Point
+               dmtc1 r_dst, fr_src */
+            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
+         } else {
+             HReg Hi, Lo;
+             r_dst = newVRegD(env);
+             iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
+             r_dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
+         }
          return r_dst;
       }
       case Iop_I32StoF64: {
-         vassert(mode64);
+         vassert(fp_mode64);
          HReg dst = newVRegF(env);
          HReg tmp = newVRegF(env);
          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
 
          /* Move Word to Floating Point
-            mtc1 tmp1, r_src */
+            mtc1 tmp, r_src */
          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
 
          /* and do convert */
@@ -3081,28 +3132,28 @@
                   op = Mfp_DIVS;
                   break;
                case Iop_DivF64:
-                  vassert(mode64);
+                  vassert(fp_mode64);
                   op = Mfp_DIVD;
                   break;
                case Iop_MulF32:
                   op = Mfp_MULS;
                   break;
                case Iop_MulF64:
-                  vassert(mode64);
+                  vassert(fp_mode64);
                   op = Mfp_MULD;
                   break;
                case Iop_AddF32:
                   op = Mfp_ADDS;
                   break;
                case Iop_AddF64:
-                  vassert(mode64);
+                  vassert(fp_mode64);
                   op = Mfp_ADDD;
                   break;
                case Iop_SubF32:
                   op = Mfp_SUBS;
                   break;
                case Iop_SubF64:
-                  vassert(mode64);
+                  vassert(fp_mode64);
                   op = Mfp_SUBD;
                   break;
                default:
@@ -3172,23 +3223,29 @@
 
          case Iop_I64StoF64: {
             HReg r_dst = newVRegF(env);
-
             MIPSAMode *am_addr;
-            HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
-            HReg tmp = newVRegF(env);
+            HReg tmp, fr_src;
+            if (mode64) {
+               tmp = newVRegF(env);
+               fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
+               /* Move SP down 8 bytes */
+               sub_from_sp(env, 8);
+               am_addr = MIPSAMode_IR(0, StackPointer(mode64));
 
-            /* Move SP down 8 bytes */
-            sub_from_sp(env, 8);
-            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+               /* store as I64 */
+               addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
 
-            /* store as I64 */
-            addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
+               /* load as Ity_F64 */
+               addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
 
-            /* load as Ity_F64 */
-            addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
-
-            /* Reset SP */
-            add_to_sp(env, 8);
+               /* Reset SP */
+               add_to_sp(env, 8);
+            } else {
+               HReg Hi, Lo;
+               tmp = newVRegD(env);
+               iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
+               tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
+            }
 
             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
@@ -3199,23 +3256,29 @@
 
          case Iop_I64StoF32: {
             HReg r_dst = newVRegF(env);
-
             MIPSAMode *am_addr;
-            HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
-            HReg tmp = newVRegF(env);
+            HReg fr_src, tmp;
+            if (mode64) {
+               tmp = newVRegF(env);
+               fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
+               /* Move SP down 8 bytes */
+               sub_from_sp(env, 8);
+               am_addr = MIPSAMode_IR(0, StackPointer(mode64));
 
-            /* Move SP down 8 bytes */
-            sub_from_sp(env, 8);
-            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+               /* store as I64 */
+               addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
 
-            /* store as I64 */
-            addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
+               /* load as Ity_F64 */
+               addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
 
-            /* load as Ity_F64 */
-            addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
-
-            /* Reset SP */
-            add_to_sp(env, 8);
+               /* Reset SP */
+               add_to_sp(env, 8);
+            } else {
+               HReg Hi, Lo;
+               tmp = newVRegD(env);
+               iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
+               tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
+            }
 
             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSL, r_dst, tmp));
@@ -3438,19 +3501,14 @@
    if (e->tag == Iex_Binop) {
       switch (e->Iex.Binop.op) {
          case Iop_RoundF64toInt: {
-            HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
-            MIPSRH *fmt = iselWordExpr_RH(env, False, e->Iex.Binop.arg1);
-            HReg valD1 = newVRegD(env);
+            HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+            HReg dst = newVRegD(env);
 
-            if (fmt->Mrh.Imm.imm16 == 0x3)
-               addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, valD1, valD));
-            else if (fmt->Mrh.Imm.imm16 == 0x2)
-               addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, valD1, valD));
-            else if (fmt->Mrh.Imm.imm16 == 0x0)
-               addInstr(env, MIPSInstr_FpConvert(Mfp_ROUNDLD, valD1, valD));
-            else
-               vassert(0);
-            return valD1;
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, dst, src));
+            set_MIPS_rounding_default(env);
+
+            return dst; 
          }
 
          case Iop_SqrtF64: {
@@ -4047,6 +4105,7 @@
       case Ijk_NoDecode:
       case Ijk_NoRedir:
       case Ijk_SigBUS:
+      case Ijk_SigILL:
       case Ijk_SigTRAP:
       case Ijk_SigFPE_IntDiv:
       case Ijk_SigFPE_IntOvf:
@@ -4097,11 +4156,16 @@
            || VEX_PRID_COMP_NETLOGIC);
 
    mode64 = arch_host != VexArchMIPS32;
+#if (__mips_fpr==64)
+   fp_mode64 = ((VEX_MIPS_REV(hwcaps_host) == VEX_PRID_CPU_32FPR)
+                || arch_host == VexArchMIPS64);
+#endif
 
    /* Make up an initial environment to use. */
    env = LibVEX_Alloc(sizeof(ISelEnv));
    env->vreg_ctr = 0;
    env->mode64 = mode64;
+   env->fp_mode64 = fp_mode64;
 
    /* Set up output code array. */
    env->code = newHInstrArray();
@@ -4166,6 +4230,7 @@
          default:
             ppIRType(bb->tyenv->types[i]);
             vpanic("iselBB(mips): IRTemp type");
+            break;
       }
       env->vregmap[i] = hreg;
       env->vregmapHI[i] = hregHI;
diff --git a/priv/ir_defs.c b/priv/ir_defs.c
index 575575c..87b0b63 100644
--- a/priv/ir_defs.c
+++ b/priv/ir_defs.c
@@ -1414,6 +1414,7 @@
       case Ijk_MapFail:       vex_printf("MapFail"); break;
       case Ijk_TInval:        vex_printf("Invalidate"); break;
       case Ijk_NoRedir:       vex_printf("NoRedir"); break;
+      case Ijk_SigILL:        vex_printf("SigILL"); break;
       case Ijk_SigTRAP:       vex_printf("SigTRAP"); break;
       case Ijk_SigSEGV:       vex_printf("SigSEGV"); break;
       case Ijk_SigBUS:        vex_printf("SigBUS"); break;
diff --git a/pub/libvex.h b/pub/libvex.h
index 4cc6156..2d40833 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -200,10 +200,15 @@
 #define VEX_PRID_IMP_34K        0x9500
 #define VEX_PRID_IMP_74K        0x9700
 
+/* CPU has FPU and 32 dbl. prec. FP registers */
+#define VEX_PRID_CPU_32FPR      0x00000040
+
 /* Get MIPS Company ID from HWCAPS */
 #define VEX_MIPS_COMP_ID(x) ((x) & 0x00FF0000)
 /* Get MIPS Processor ID from HWCAPS */
-#define VEX_MIPS_PROC_ID(x) ((x) & 0x0000FFFF)
+#define VEX_MIPS_PROC_ID(x) ((x) & 0x0000FF00)
+/* Get MIPS Revision from HWCAPS */
+#define VEX_MIPS_REV(x) ((x) & 0x000000FF)
 /* Check if the processor supports DSP ASE Rev 2. */
 #define VEX_MIPS_PROC_DSP2(x) ((VEX_MIPS_COMP_ID(x) == VEX_PRID_COMP_MIPS) && \
                                (VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_74K))
diff --git a/pub/libvex_guest_mips32.h b/pub/libvex_guest_mips32.h
index 95c2a58..65318fe 100644
--- a/pub/libvex_guest_mips32.h
+++ b/pub/libvex_guest_mips32.h
@@ -41,81 +41,81 @@
 typedef
    struct {
       /* CPU Registers */
-      /*   0 */ UInt guest_r0; /* Hardwired to 0 */
-      /*   4 */ UInt guest_r1;   /* Assembler temporary */
-      /*   8 */ UInt guest_r2;   /* Values for function returns ...*/
-      /*   12 */ UInt guest_r3;   /* ...and expression evaluation */
-      /*   16 */ UInt guest_r4;   /* Function arguments */
-      /*   20 */ UInt guest_r5;
-      /*   24 */ UInt guest_r6;
-      /*   28 */ UInt guest_r7;
-      /*   32 */ UInt guest_r8;   /* Temporaries */
-      /*   36 */ UInt guest_r9;
-      /*   40 */ UInt guest_r10;
-      /*   44 */ UInt guest_r11;
-      /*   48 */ UInt guest_r12;
-      /*   52 */ UInt guest_r13;
-      /*   56 */ UInt guest_r14;
-      /*   60 */ UInt guest_r15;
-      /*   64 */ UInt guest_r16;   /* Saved temporaries */
-      /*   68 */ UInt guest_r17;
-      /*   72 */ UInt guest_r18;
-      /*   76 */ UInt guest_r19;
-      /*   80 */ UInt guest_r20;
-      /*   84 */ UInt guest_r21;
-      /*   88 */ UInt guest_r22;
-      /*   92 */ UInt guest_r23;
-      /*   96 */ UInt guest_r24;   /* Temporaries */
-      /*   100 */ UInt guest_r25;
-      /*   104 */ UInt guest_r26;   /* Reserved for OS kernel */
-      /*   108 */ UInt guest_r27;
-      /*   112 */ UInt guest_r28;   /* Global pointer */
-      /*   116 */ UInt guest_r29;   /* Stack pointer */
-      /*   120 */ UInt guest_r30;   /* Frame pointer */
-      /*   124 */ UInt guest_r31;   /* Return address */
-      /*   128 */ UInt guest_PC;   /* Program counter */
-      /*   132 */ UInt guest_HI;/* Multiply and divide register higher result */
-      /*   136 */ UInt guest_LO;/* Multiply and divide register lower result */
+      /* 0 */ UInt guest_r0;   /* Hardwired to 0 */
+      /* 4 */ UInt guest_r1;   /* Assembler temporary */
+      /* 8 */ UInt guest_r2;   /* Values for function returns ...*/
+      /* 12 */ UInt guest_r3;  /* ...and expression evaluation */
+      /* 16 */ UInt guest_r4;  /* Function arguments */
+      /* 20 */ UInt guest_r5;
+      /* 24 */ UInt guest_r6;
+      /* 28 */ UInt guest_r7;
+      /* 32 */ UInt guest_r8;  /* Temporaries */
+      /* 36 */ UInt guest_r9;
+      /* 40 */ UInt guest_r10;
+      /* 44 */ UInt guest_r11;
+      /* 48 */ UInt guest_r12;
+      /* 52 */ UInt guest_r13;
+      /* 56 */ UInt guest_r14;
+      /* 60 */ UInt guest_r15;
+      /* 64 */ UInt guest_r16;  /* Saved temporaries */
+      /* 68 */ UInt guest_r17;
+      /* 72 */ UInt guest_r18;
+      /* 76 */ UInt guest_r19;
+      /* 80 */ UInt guest_r20;
+      /* 84 */ UInt guest_r21;
+      /* 88 */ UInt guest_r22;
+      /* 92 */ UInt guest_r23;
+      /* 96 */ UInt guest_r24;  /* Temporaries */
+      /* 100 */ UInt guest_r25;
+      /* 104 */ UInt guest_r26;  /* Reserved for OS kernel */
+      /* 108 */ UInt guest_r27;
+      /* 112 */ UInt guest_r28;  /* Global pointer */
+      /* 116 */ UInt guest_r29;  /* Stack pointer */
+      /* 120 */ UInt guest_r30;  /* Frame pointer */
+      /* 124 */ UInt guest_r31;  /* Return address */
+      /* 128 */ UInt guest_PC;  /* Program counter */
+      /* 132 */ UInt guest_HI;  /* Multiply and divide register higher result */
+      /* 136 */ UInt guest_LO;  /* Multiply and divide register lower result */
 
       /* FPU Registers */
-      /*   140 */ UInt guest_f0; /* Floting point general purpose registers */
-      /*   144 */ UInt guest_f1;
-      /*   148 */ UInt guest_f2;
-      /*   152 */ UInt guest_f3;
-      /*   156 */ UInt guest_f4;
-      /*   160 */ UInt guest_f5;
-      /*   164 */ UInt guest_f6;
-      /*   168 */ UInt guest_f7;
-      /*   172 */ UInt guest_f8;
-      /*   176 */ UInt guest_f9;
-      /*   180 */ UInt guest_f10;
-      /*   184 */ UInt guest_f11;
-      /*   188 */ UInt guest_f12;
-      /*   192 */ UInt guest_f13;
-      /*   196 */ UInt guest_f14;
-      /*   200 */ UInt guest_f15;
-      /*   204 */ UInt guest_f16;
-      /*   208 */ UInt guest_f17;
-      /*   212 */ UInt guest_f18;
-      /*   216 */ UInt guest_f19;
-      /*   220 */ UInt guest_f20;
-      /*   224 */ UInt guest_f21;
-      /*   228 */ UInt guest_f22;
-      /*   232 */ UInt guest_f23;
-      /*   236 */ UInt guest_f24;
-      /*   240 */ UInt guest_f25;
-      /*   244 */ UInt guest_f26;
-      /*   248 */ UInt guest_f27;
-      /*   252 */ UInt guest_f28;
-      /*   256 */ UInt guest_f29;
-      /*   260 */ UInt guest_f30;
-      /*   264 */ UInt guest_f31;
-  
-      /*   268 */ UInt guest_FIR;
-      /*   272 */ UInt guest_FCCR;
-      /*   276 */ UInt guest_FEXR;
-      /*   280 */ UInt guest_FENR;
-      /*   284 */ UInt guest_FCSR;
+      /* 144 */ ULong guest_f0;  /* Floating point general purpose registers */
+      /* 152 */ ULong guest_f1;
+      /* 160 */ ULong guest_f2;
+      /* 168 */ ULong guest_f3;
+      /* 176 */ ULong guest_f4;
+      /* 184 */ ULong guest_f5;
+      /* 192 */ ULong guest_f6;
+      /* 200 */ ULong guest_f7;
+      /* 208 */ ULong guest_f8;
+      /* 216 */ ULong guest_f9;
+      /* 224 */ ULong guest_f10;
+      /* 232 */ ULong guest_f11;
+      /* 240 */ ULong guest_f12;
+      /* 248 */ ULong guest_f13;
+      /* 256 */ ULong guest_f14;
+      /* 264 */ ULong guest_f15;
+      /* 272 */ ULong guest_f16;
+      /* 280 */ ULong guest_f17;
+      /* 288 */ ULong guest_f18;
+      /* 296 */ ULong guest_f19;
+      /* 304 */ ULong guest_f20;
+      /* 312 */ ULong guest_f21;
+      /* 320 */ ULong guest_f22;
+      /* 328 */ ULong guest_f23;
+      /* 336 */ ULong guest_f24;
+      /* 344 */ ULong guest_f25;
+      /* 352 */ ULong guest_f26;
+      /* 360 */ ULong guest_f27;
+      /* 368 */ ULong guest_f28;
+      /* 376 */ ULong guest_f29;
+      /* 384 */ ULong guest_f30;
+      /* 392 */ ULong guest_f31;
+
+      /* 400 */ UInt guest_FIR;
+      /* 404 */ UInt guest_FCCR;
+      /* 408 */ UInt guest_FEXR;
+      /* 412 */ UInt guest_FENR;
+      /* 416 */ UInt guest_FCSR;
 
       /* TLS pointer for the thread. It's read-only in user space.
          On Linux it is set in user space by various thread-related
@@ -126,29 +126,28 @@
          environments, the UserLocal register is a pointer to a
          thread-specific storage block.
       */
-      /*   288 */ UInt guest_ULR;
+      /* 420 */ UInt guest_ULR;
 
       /* Emulation notes */
-          UInt   guest_EMNOTE;  /* 292 */
+      /* 424 */ UInt guest_EMNOTE;
 
       /* For clflush: record start and length of area to invalidate */
-        UInt guest_TISTART;     /* 296 */
-        UInt guest_TILEN;       /* 300 */ 
-        UInt guest_NRADDR;      /* 304 */
+      /* 428 */ UInt guest_TISTART;
+      /* 432 */ UInt guest_TILEN;
+      /* 436 */ UInt guest_NRADDR;
 
-        UInt host_EvC_FAILADDR; /* 308 */
-        UInt host_EvC_COUNTER;  /* 312 */
-        UInt guest_COND;        /* 316 */
+      /* 440 */ UInt host_EvC_FAILADDR;
+      /* 444 */ UInt host_EvC_COUNTER;
+      /* 448 */ UInt guest_COND;
 
-        UInt padding1;
       /* MIPS32 DSP ASE(r2) specific registers. */
-        UInt guest_DSPControl;  /* 324 */
-        ULong guest_ac0;        /* 328 */
-        ULong guest_ac1;        /* 336 */
-        ULong guest_ac2;        /* 344 */
-        ULong guest_ac3;        /* 352 */
-        
-        UInt padding[2];
+      /* 452 */ UInt guest_DSPControl;
+      /* 456 */ ULong guest_ac0;
+      /* 464 */ ULong guest_ac1;
+      /* 472 */ ULong guest_ac2;
+      /* 480 */ ULong guest_ac3;
+
+        UInt padding;
 } VexGuestMIPS32State;
 /*---------------------------------------------------------------*/
 /*--- Utility functions for MIPS32 guest stuff.               ---*/
diff --git a/pub/libvex_ir.h b/pub/libvex_ir.h
index c89b608..39d45e4 100644
--- a/pub/libvex_ir.h
+++ b/pub/libvex_ir.h
@@ -2107,6 +2107,7 @@
       Ijk_MapFail,        /* Vex-provided address translation failed */
       Ijk_TInval,         /* Invalidate translations before continuing. */
       Ijk_NoRedir,        /* Jump to un-redirected guest addr */
+      Ijk_SigILL,         /* current instruction synths SIGILL */
       Ijk_SigTRAP,        /* current instruction synths SIGTRAP */
       Ijk_SigSEGV,        /* current instruction synths SIGSEGV */
       Ijk_SigBUS,         /* current instruction synths SIGBUS */
diff --git a/pub/libvex_trc_values.h b/pub/libvex_trc_values.h
index c0f3cc8..58a8e30 100644
--- a/pub/libvex_trc_values.h
+++ b/pub/libvex_trc_values.h
@@ -68,6 +68,9 @@
 #define VEX_TRC_JMP_SIGFPE_INTOVF     99  /* deliver SIGFPE (integer overflow)
                                              before continuing */
 
+#define VEX_TRC_JMP_SIGILL     101  /* deliver SIGILL (Illegal instruction)
+                                       before continuing */
+
 #define VEX_TRC_JMP_EMWARN     63  /* deliver emulation warning before
                                       continuing */
 #define VEX_TRC_JMP_EMFAIL     83  /* emulation fatal error; abort system */