]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips: code refactoring (NFC)
authorPetar Jovanovic <mips32r2@gmail.com>
Wed, 27 Mar 2019 18:42:05 +0000 (18:42 +0000)
committerPetar Jovanovic <mips32r2@gmail.com>
Wed, 27 Mar 2019 18:42:05 +0000 (18:42 +0000)
Code in VEX/priv/guest_mips_toIR.c is notably refactored.
DSP ASE dissasembly has been put in a separate file: guest_mipsdsp_toIR.c.

Patch by Aleksandar Rikalo.

Makefile.vex.am
VEX/Makefile-gcc
VEX/priv/guest_mips_toIR.c [changed mode: 0644->0755]
VEX/priv/guest_mipsdsp_toIR.c [new file with mode: 0644]
VEX/priv/mips_defs.h [new file with mode: 0644]

index 2b54b8a55ba6c1a484d9c2cfa96baf6e429ad6b3..10e1890f63f339d504e7f4b71ed3915ed55b8159 100644 (file)
@@ -47,6 +47,7 @@ noinst_HEADERS = \
        priv/guest_arm64_defs.h \
        priv/guest_s390_defs.h \
        priv/guest_mips_defs.h \
+       priv/mips_defs.h \
        priv/host_generic_regs.h \
        priv/host_generic_simd64.h \
        priv/host_generic_simd128.h \
@@ -143,6 +144,7 @@ LIBVEX_SOURCES_COMMON = \
        priv/guest_s390_helpers.c \
        priv/guest_s390_toIR.c \
        priv/guest_mips_helpers.c \
+       priv/guest_mipsdsp_toIR.c \
        priv/guest_mips_toIR.c \
        priv/host_generic_regs.c \
        priv/host_generic_simd64.c \
index 0822712debbfb436f69ef4de9831f7dec1483622..0b94e13c5f72397f8d9d63efa46455c54c33dd8c 100644 (file)
@@ -34,6 +34,7 @@ PRIV_HEADERS =        priv/host_x86_defs.h                    \
                priv/guest_arm_defs.h                   \
                priv/guest_ppc_defs.h                   \
                priv/guest_mips_defs.h                  \
+               priv/mips_defs.h                        \
                priv/s390_disasm.h                      \
                priv/s390_defs.h                        \
                priv/ir_match.h                         \
@@ -82,6 +83,7 @@ LIB_OBJS =    priv/ir_defs.o                          \
                priv/guest_arm64_toIR.o                 \
                priv/guest_ppc_toIR.o                   \
                priv/guest_s390_toIR.o                  \
+               priv/guest_mipsdsp_toIR.o               \
                priv/guest_mips_toIR.o
 
 PUB_INCLUDES = -Ipub
@@ -409,6 +411,10 @@ priv/guest_mips_helpers.o: $(ALL_HEADERS) priv/guest_mips_helpers.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest_mips_helpers.o \
                                         -c priv/guest_mips_helpers.c
 
+priv/guest_mipsdsp_toIR.o: $(ALL_HEADERS) priv/guest_mipsdsp_toIR.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest_mipsdsp_toIR.o \
+                                        -c priv/guest_mipsdsp_toIR.c
+
 priv/guest_mips_toIR.o: $(ALL_HEADERS) priv/guest_mips_toIR.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest_mips_toIR.o \
                                         -c priv/guest_mips_toIR.c
old mode 100644 (file)
new mode 100755 (executable)
index 4748ba4..eb437ec
@@ -40,6 +40,7 @@
 #include "main_globals.h"
 #include "guest_generic_bb_to_IR.h"
 #include "guest_mips_defs.h"
+#include "mips_defs.h"
 
 /*------------------------------------------------------------*/
 /*---                      Globals                         ---*/
@@ -55,7 +56,7 @@
 static VexEndness host_endness;
 
 /* Pointer to the guest code area. */
-static const UChar *guest_code;
+const UChar *guest_code;
 
 /* CONST: The guest address for the instruction currently being
    translated. */
@@ -66,14 +67,14 @@ static Addr64 guest_PC_curr_instr;
 #endif
 
 /* MOD: The IRSB* into which we're generating code. */
-static IRSB *irsb;
+IRSB *irsb;
 
 /* Is our guest binary 32 or 64bit? Set at each call to
    disInstr_MIPS below. */
-static Bool mode64 = False;
+Bool mode64 = False;
 
 /* CPU has FPU and 32 dbl. prec. FP registers. */
-static Bool fp_mode64 = False;
+ static Bool fp_mode64 = False;
 
 /* FPU works in FRE mode */
 static Bool fp_mode64_fre = False;
@@ -85,14 +86,6 @@ static Bool has_msa = False;
 #define ONE_SINGLE 0x3F800000
 #define ONE_DOUBLE 0x3FF0000000000000ULL
 
-/*------------------------------------------------------------*/
-/*---                  Debugging output                    ---*/
-/*------------------------------------------------------------*/
-
-#define DIP(format, args...)           \
-   if (vex_traceflags & VEX_TRACE_FE)  \
-      vex_printf(format, ## args)
-
 /*------------------------------------------------------------*/
 /*--- Helper bits and pieces for deconstructing the        ---*/
 /*--- mips insn stream.                                    ---*/
@@ -106,12812 +99,6014 @@ static UInt integerGuestRegOffset(UInt iregNo)
       registers are accessed, but I don't think that ever happens on
       MIPS. */
    UInt ret;
-   if (!mode64)
-      switch (iregNo) {
-         case 0:
-            ret = offsetof(VexGuestMIPS32State, guest_r0); break;
-         case 1:
-            ret = offsetof(VexGuestMIPS32State, guest_r1); break;
-         case 2:
-            ret = offsetof(VexGuestMIPS32State, guest_r2); break;
-         case 3:
-            ret = offsetof(VexGuestMIPS32State, guest_r3); break;
-         case 4:
-            ret = offsetof(VexGuestMIPS32State, guest_r4); break;
-         case 5:
-            ret = offsetof(VexGuestMIPS32State, guest_r5); break;
-         case 6:
-            ret = offsetof(VexGuestMIPS32State, guest_r6); break;
-         case 7:
-            ret = offsetof(VexGuestMIPS32State, guest_r7); break;
-         case 8:
-            ret = offsetof(VexGuestMIPS32State, guest_r8); break;
-         case 9:
-            ret = offsetof(VexGuestMIPS32State, guest_r9); break;
-         case 10:
-            ret = offsetof(VexGuestMIPS32State, guest_r10); break;
-         case 11:
-            ret = offsetof(VexGuestMIPS32State, guest_r11); break;
-         case 12:
-            ret = offsetof(VexGuestMIPS32State, guest_r12); break;
-         case 13:
-            ret = offsetof(VexGuestMIPS32State, guest_r13); break;
-         case 14:
-            ret = offsetof(VexGuestMIPS32State, guest_r14); break;
-         case 15:
-            ret = offsetof(VexGuestMIPS32State, guest_r15); break;
-         case 16:
-            ret = offsetof(VexGuestMIPS32State, guest_r16); break;
-         case 17:
-            ret = offsetof(VexGuestMIPS32State, guest_r17); break;
-         case 18:
-            ret = offsetof(VexGuestMIPS32State, guest_r18); break;
-         case 19:
-            ret = offsetof(VexGuestMIPS32State, guest_r19); break;
-         case 20:
-            ret = offsetof(VexGuestMIPS32State, guest_r20); break;
-         case 21:
-            ret = offsetof(VexGuestMIPS32State, guest_r21); break;
-         case 22:
-            ret = offsetof(VexGuestMIPS32State, guest_r22); break;
-         case 23:
-            ret = offsetof(VexGuestMIPS32State, guest_r23); break;
-         case 24:
-            ret = offsetof(VexGuestMIPS32State, guest_r24); break;
-         case 25:
-            ret = offsetof(VexGuestMIPS32State, guest_r25); break;
-         case 26:
-            ret = offsetof(VexGuestMIPS32State, guest_r26); break;
-         case 27:
-            ret = offsetof(VexGuestMIPS32State, guest_r27); break;
-         case 28:
-            ret = offsetof(VexGuestMIPS32State, guest_r28); break;
-         case 29:
-            ret = offsetof(VexGuestMIPS32State, guest_r29); break;
-         case 30:
-            ret = offsetof(VexGuestMIPS32State, guest_r30); break;
-         case 31:
-            ret = offsetof(VexGuestMIPS32State, guest_r31); break;
-         default:
-            vassert(0);
-            break;
-      }
-   else
-      switch (iregNo) {
-         case 0:
-            ret = offsetof(VexGuestMIPS64State, guest_r0); break;
-         case 1:
-            ret = offsetof(VexGuestMIPS64State, guest_r1); break;
-         case 2:
-            ret = offsetof(VexGuestMIPS64State, guest_r2); break;
-         case 3:
-            ret = offsetof(VexGuestMIPS64State, guest_r3); break;
-         case 4:
-            ret = offsetof(VexGuestMIPS64State, guest_r4); break;
-         case 5:
-            ret = offsetof(VexGuestMIPS64State, guest_r5); break;
-         case 6:
-            ret = offsetof(VexGuestMIPS64State, guest_r6); break;
-         case 7:
-            ret = offsetof(VexGuestMIPS64State, guest_r7); break;
-         case 8:
-            ret = offsetof(VexGuestMIPS64State, guest_r8); break;
-         case 9:
-            ret = offsetof(VexGuestMIPS64State, guest_r9); break;
-         case 10:
-            ret = offsetof(VexGuestMIPS64State, guest_r10); break;
-         case 11:
-            ret = offsetof(VexGuestMIPS64State, guest_r11); break;
-         case 12:
-            ret = offsetof(VexGuestMIPS64State, guest_r12); break;
-         case 13:
-            ret = offsetof(VexGuestMIPS64State, guest_r13); break;
-         case 14:
-            ret = offsetof(VexGuestMIPS64State, guest_r14); break;
-         case 15:
-            ret = offsetof(VexGuestMIPS64State, guest_r15); break;
-         case 16:
-            ret = offsetof(VexGuestMIPS64State, guest_r16); break;
-         case 17:
-            ret = offsetof(VexGuestMIPS64State, guest_r17); break;
-         case 18:
-            ret = offsetof(VexGuestMIPS64State, guest_r18); break;
-         case 19:
-            ret = offsetof(VexGuestMIPS64State, guest_r19); break;
-         case 20:
-            ret = offsetof(VexGuestMIPS64State, guest_r20); break;
-         case 21:
-            ret = offsetof(VexGuestMIPS64State, guest_r21); break;
-         case 22:
-            ret = offsetof(VexGuestMIPS64State, guest_r22); break;
-         case 23:
-            ret = offsetof(VexGuestMIPS64State, guest_r23); break;
-         case 24:
-            ret = offsetof(VexGuestMIPS64State, guest_r24); break;
-         case 25:
-            ret = offsetof(VexGuestMIPS64State, guest_r25); break;
-         case 26:
-            ret = offsetof(VexGuestMIPS64State, guest_r26); break;
-         case 27:
-            ret = offsetof(VexGuestMIPS64State, guest_r27); break;
-         case 28:
-            ret = offsetof(VexGuestMIPS64State, guest_r28); break;
-         case 29:
-            ret = offsetof(VexGuestMIPS64State, guest_r29); break;
-         case 30:
-            ret = offsetof(VexGuestMIPS64State, guest_r30); break;
-         case 31:
-            ret = offsetof(VexGuestMIPS64State, guest_r31); break;
-         default:
-            vassert(0);
-            break;
-      }
-   return ret;
-}
-
-#if defined(VGP_mips32_linux)
-#define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
-#else
-#define OFFB_PC     offsetof(VexGuestMIPS64State, guest_PC)
-#endif
 
-/* ---------------- Floating point registers ---------------- */
-
-static UInt floatGuestRegOffset(UInt fregNo)
-{
-   vassert(fregNo < 32);
-   UInt ret;
    if (!mode64)
-      switch (fregNo) {
-         case 0:
-            ret = offsetof(VexGuestMIPS32State, guest_f0); break;
-         case 1:
-            ret = offsetof(VexGuestMIPS32State, guest_f1); break;
-         case 2:
-            ret = offsetof(VexGuestMIPS32State, guest_f2); break;
-         case 3:
-            ret = offsetof(VexGuestMIPS32State, guest_f3); break;
-         case 4:
-            ret = offsetof(VexGuestMIPS32State, guest_f4); break;
-         case 5:
-            ret = offsetof(VexGuestMIPS32State, guest_f5); break;
-         case 6:
-            ret = offsetof(VexGuestMIPS32State, guest_f6); break;
-         case 7:
-            ret = offsetof(VexGuestMIPS32State, guest_f7); break;
-         case 8:
-            ret = offsetof(VexGuestMIPS32State, guest_f8); break;
-         case 9:
-            ret = offsetof(VexGuestMIPS32State, guest_f9); break;
-         case 10:
-            ret = offsetof(VexGuestMIPS32State, guest_f10); break;
-         case 11:
-            ret = offsetof(VexGuestMIPS32State, guest_f11); break;
-         case 12:
-            ret = offsetof(VexGuestMIPS32State, guest_f12); break;
-         case 13:
-            ret = offsetof(VexGuestMIPS32State, guest_f13); break;
-         case 14:
-            ret = offsetof(VexGuestMIPS32State, guest_f14); break;
-         case 15:
-            ret = offsetof(VexGuestMIPS32State, guest_f15); break;
-         case 16:
-            ret = offsetof(VexGuestMIPS32State, guest_f16); break;
-         case 17:
-            ret = offsetof(VexGuestMIPS32State, guest_f17); break;
-         case 18:
-            ret = offsetof(VexGuestMIPS32State, guest_f18); break;
-         case 19:
-            ret = offsetof(VexGuestMIPS32State, guest_f19); break;
-         case 20:
-            ret = offsetof(VexGuestMIPS32State, guest_f20); break;
-         case 21:
-            ret = offsetof(VexGuestMIPS32State, guest_f21); break;
-         case 22:
-            ret = offsetof(VexGuestMIPS32State, guest_f22); break;
-         case 23:
-            ret = offsetof(VexGuestMIPS32State, guest_f23); break;
-         case 24:
-            ret = offsetof(VexGuestMIPS32State, guest_f24); break;
-         case 25:
-            ret = offsetof(VexGuestMIPS32State, guest_f25); break;
-         case 26:
-            ret = offsetof(VexGuestMIPS32State, guest_f26); break;
-         case 27:
-            ret = offsetof(VexGuestMIPS32State, guest_f27); break;
-         case 28:
-            ret = offsetof(VexGuestMIPS32State, guest_f28); break;
-         case 29:
-            ret = offsetof(VexGuestMIPS32State, guest_f29); break;
-         case 30:
-            ret = offsetof(VexGuestMIPS32State, guest_f30); break;
-         case 31:
-            ret = offsetof(VexGuestMIPS32State, guest_f31); break;
-         default:
-            vassert(0);
-            break;
-      }
-   else
-      switch (fregNo) {
-         case 0:
-            ret = offsetof(VexGuestMIPS64State, guest_f0); break;
-         case 1:
-            ret = offsetof(VexGuestMIPS64State, guest_f1); break;
-         case 2:
-            ret = offsetof(VexGuestMIPS64State, guest_f2); break;
-         case 3:
-            ret = offsetof(VexGuestMIPS64State, guest_f3); break;
-         case 4:
-            ret = offsetof(VexGuestMIPS64State, guest_f4); break;
-         case 5:
-            ret = offsetof(VexGuestMIPS64State, guest_f5); break;
-         case 6:
-            ret = offsetof(VexGuestMIPS64State, guest_f6); break;
-         case 7:
-            ret = offsetof(VexGuestMIPS64State, guest_f7); break;
-         case 8:
-            ret = offsetof(VexGuestMIPS64State, guest_f8); break;
-         case 9:
-            ret = offsetof(VexGuestMIPS64State, guest_f9); break;
-         case 10:
-            ret = offsetof(VexGuestMIPS64State, guest_f10); break;
-         case 11:
-            ret = offsetof(VexGuestMIPS64State, guest_f11); break;
-         case 12:
-            ret = offsetof(VexGuestMIPS64State, guest_f12); break;
-         case 13:
-            ret = offsetof(VexGuestMIPS64State, guest_f13); break;
-         case 14:
-            ret = offsetof(VexGuestMIPS64State, guest_f14); break;
-         case 15:
-            ret = offsetof(VexGuestMIPS64State, guest_f15); break;
-         case 16:
-            ret = offsetof(VexGuestMIPS64State, guest_f16); break;
-         case 17:
-            ret = offsetof(VexGuestMIPS64State, guest_f17); break;
-         case 18:
-            ret = offsetof(VexGuestMIPS64State, guest_f18); break;
-         case 19:
-            ret = offsetof(VexGuestMIPS64State, guest_f19); break;
-         case 20:
-            ret = offsetof(VexGuestMIPS64State, guest_f20); break;
-         case 21:
-            ret = offsetof(VexGuestMIPS64State, guest_f21); break;
-         case 22:
-            ret = offsetof(VexGuestMIPS64State, guest_f22); break;
-         case 23:
-            ret = offsetof(VexGuestMIPS64State, guest_f23); break;
-         case 24:
-            ret = offsetof(VexGuestMIPS64State, guest_f24); break;
-         case 25:
-            ret = offsetof(VexGuestMIPS64State, guest_f25); break;
-         case 26:
-            ret = offsetof(VexGuestMIPS64State, guest_f26); break;
-         case 27:
-            ret = offsetof(VexGuestMIPS64State, guest_f27); break;
-         case 28:
-            ret = offsetof(VexGuestMIPS64State, guest_f28); break;
-         case 29:
-            ret = offsetof(VexGuestMIPS64State, guest_f29); break;
-         case 30:
-            ret = offsetof(VexGuestMIPS64State, guest_f30); break;
-         case 31:
-            ret = offsetof(VexGuestMIPS64State, guest_f31); break;
-         default:
-            vassert(0);
-            break;
-      }
-   return ret;
-}
-
-/* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
-
-static UInt accumulatorGuestRegOffset(UInt acNo)
-{
-   vassert(!mode64);
-   vassert(acNo <= 3);
-   UInt ret;
-   switch (acNo) {
-      case 0:
-         ret = offsetof(VexGuestMIPS32State, guest_ac0); break;
-      case 1:
-         ret = offsetof(VexGuestMIPS32State, guest_ac1); break;
-      case 2:
-         ret = offsetof(VexGuestMIPS32State, guest_ac2); break;
-      case 3:
-         ret = offsetof(VexGuestMIPS32State, guest_ac3); break;
-      default:
-         vassert(0);
-    break;
-   }
-   return ret;
-}
-
-/* ---------------- MIPS32 MSA registers ---------------- */
-
-static UInt msaGuestRegOffset(UInt msaRegNo) {
-   vassert(msaRegNo <= 31);
-   UInt ret;
-
-   if (mode64) {
-      switch (msaRegNo) {
+      switch (iregNo) {
          case 0:
-            ret = offsetof(VexGuestMIPS64State, guest_w0);
+            ret = offsetof(VexGuestMIPS32State, guest_r0);
             break;
 
          case 1:
-            ret = offsetof(VexGuestMIPS64State, guest_w1);
+            ret = offsetof(VexGuestMIPS32State, guest_r1);
             break;
 
          case 2:
-            ret = offsetof(VexGuestMIPS64State, guest_w2);
+            ret = offsetof(VexGuestMIPS32State, guest_r2);
             break;
 
          case 3:
-            ret = offsetof(VexGuestMIPS64State, guest_w3);
+            ret = offsetof(VexGuestMIPS32State, guest_r3);
             break;
 
          case 4:
-            ret = offsetof(VexGuestMIPS64State, guest_w4);
+            ret = offsetof(VexGuestMIPS32State, guest_r4);
             break;
 
          case 5:
-            ret = offsetof(VexGuestMIPS64State, guest_w5);
+            ret = offsetof(VexGuestMIPS32State, guest_r5);
             break;
 
          case 6:
-            ret = offsetof(VexGuestMIPS64State, guest_w6);
+            ret = offsetof(VexGuestMIPS32State, guest_r6);
             break;
 
          case 7:
-            ret = offsetof(VexGuestMIPS64State, guest_w7);
+            ret = offsetof(VexGuestMIPS32State, guest_r7);
             break;
 
          case 8:
-            ret = offsetof(VexGuestMIPS64State, guest_w8);
+            ret = offsetof(VexGuestMIPS32State, guest_r8);
             break;
 
          case 9:
-            ret = offsetof(VexGuestMIPS64State, guest_w9);
+            ret = offsetof(VexGuestMIPS32State, guest_r9);
             break;
 
          case 10:
-            ret = offsetof(VexGuestMIPS64State, guest_w10);
+            ret = offsetof(VexGuestMIPS32State, guest_r10);
             break;
 
          case 11:
-            ret = offsetof(VexGuestMIPS64State, guest_w11);
+            ret = offsetof(VexGuestMIPS32State, guest_r11);
             break;
 
          case 12:
-            ret = offsetof(VexGuestMIPS64State, guest_w12);
+            ret = offsetof(VexGuestMIPS32State, guest_r12);
             break;
 
          case 13:
-            ret = offsetof(VexGuestMIPS64State, guest_w13);
+            ret = offsetof(VexGuestMIPS32State, guest_r13);
             break;
 
          case 14:
-            ret = offsetof(VexGuestMIPS64State, guest_w14);
+            ret = offsetof(VexGuestMIPS32State, guest_r14);
             break;
 
          case 15:
-            ret = offsetof(VexGuestMIPS64State, guest_w15);
+            ret = offsetof(VexGuestMIPS32State, guest_r15);
             break;
 
          case 16:
-            ret = offsetof(VexGuestMIPS64State, guest_w16);
+            ret = offsetof(VexGuestMIPS32State, guest_r16);
             break;
 
          case 17:
-            ret = offsetof(VexGuestMIPS64State, guest_w17);
+            ret = offsetof(VexGuestMIPS32State, guest_r17);
             break;
 
          case 18:
-            ret = offsetof(VexGuestMIPS64State, guest_w18);
+            ret = offsetof(VexGuestMIPS32State, guest_r18);
             break;
 
          case 19:
-            ret = offsetof(VexGuestMIPS64State, guest_w19);
+            ret = offsetof(VexGuestMIPS32State, guest_r19);
             break;
 
          case 20:
-            ret = offsetof(VexGuestMIPS64State, guest_w20);
+            ret = offsetof(VexGuestMIPS32State, guest_r20);
             break;
 
          case 21:
-            ret = offsetof(VexGuestMIPS64State, guest_w21);
+            ret = offsetof(VexGuestMIPS32State, guest_r21);
             break;
 
          case 22:
-            ret = offsetof(VexGuestMIPS64State, guest_w22);
+            ret = offsetof(VexGuestMIPS32State, guest_r22);
             break;
 
          case 23:
-            ret = offsetof(VexGuestMIPS64State, guest_w23);
+            ret = offsetof(VexGuestMIPS32State, guest_r23);
             break;
 
          case 24:
-            ret = offsetof(VexGuestMIPS64State, guest_w24);
+            ret = offsetof(VexGuestMIPS32State, guest_r24);
             break;
 
          case 25:
-            ret = offsetof(VexGuestMIPS64State, guest_w25);
+            ret = offsetof(VexGuestMIPS32State, guest_r25);
             break;
 
          case 26:
-            ret = offsetof(VexGuestMIPS64State, guest_w26);
+            ret = offsetof(VexGuestMIPS32State, guest_r26);
             break;
 
          case 27:
-            ret = offsetof(VexGuestMIPS64State, guest_w27);
+            ret = offsetof(VexGuestMIPS32State, guest_r27);
             break;
 
          case 28:
-            ret = offsetof(VexGuestMIPS64State, guest_w28);
+            ret = offsetof(VexGuestMIPS32State, guest_r28);
             break;
 
          case 29:
-            ret = offsetof(VexGuestMIPS64State, guest_w29);
+            ret = offsetof(VexGuestMIPS32State, guest_r29);
             break;
 
          case 30:
-            ret = offsetof(VexGuestMIPS64State, guest_w30);
+            ret = offsetof(VexGuestMIPS32State, guest_r30);
             break;
 
          case 31:
-            ret = offsetof(VexGuestMIPS64State, guest_w31);
+            ret = offsetof(VexGuestMIPS32State, guest_r31);
             break;
 
          default:
             vassert(0);
             break;
       }
-   } else {
-      switch (msaRegNo) {
+   else
+      switch (iregNo) {
          case 0:
-            ret = offsetof(VexGuestMIPS32State, guest_w0);
+            ret = offsetof(VexGuestMIPS64State, guest_r0);
             break;
 
          case 1:
-            ret = offsetof(VexGuestMIPS32State, guest_w1);
+            ret = offsetof(VexGuestMIPS64State, guest_r1);
             break;
 
          case 2:
-            ret = offsetof(VexGuestMIPS32State, guest_w2);
+            ret = offsetof(VexGuestMIPS64State, guest_r2);
             break;
 
          case 3:
-            ret = offsetof(VexGuestMIPS32State, guest_w3);
+            ret = offsetof(VexGuestMIPS64State, guest_r3);
             break;
 
          case 4:
-            ret = offsetof(VexGuestMIPS32State, guest_w4);
+            ret = offsetof(VexGuestMIPS64State, guest_r4);
             break;
 
          case 5:
-            ret = offsetof(VexGuestMIPS32State, guest_w5);
+            ret = offsetof(VexGuestMIPS64State, guest_r5);
             break;
 
          case 6:
-            ret = offsetof(VexGuestMIPS32State, guest_w6);
+            ret = offsetof(VexGuestMIPS64State, guest_r6);
             break;
 
          case 7:
-            ret = offsetof(VexGuestMIPS32State, guest_w7);
+            ret = offsetof(VexGuestMIPS64State, guest_r7);
             break;
 
          case 8:
-            ret = offsetof(VexGuestMIPS32State, guest_w8);
+            ret = offsetof(VexGuestMIPS64State, guest_r8);
             break;
 
          case 9:
-            ret = offsetof(VexGuestMIPS32State, guest_w9);
+            ret = offsetof(VexGuestMIPS64State, guest_r9);
             break;
 
          case 10:
-            ret = offsetof(VexGuestMIPS32State, guest_w10);
+            ret = offsetof(VexGuestMIPS64State, guest_r10);
             break;
 
          case 11:
-            ret = offsetof(VexGuestMIPS32State, guest_w11);
+            ret = offsetof(VexGuestMIPS64State, guest_r11);
             break;
 
          case 12:
-            ret = offsetof(VexGuestMIPS32State, guest_w12);
+            ret = offsetof(VexGuestMIPS64State, guest_r12);
             break;
 
          case 13:
-            ret = offsetof(VexGuestMIPS32State, guest_w13);
+            ret = offsetof(VexGuestMIPS64State, guest_r13);
             break;
 
          case 14:
-            ret = offsetof(VexGuestMIPS32State, guest_w14);
+            ret = offsetof(VexGuestMIPS64State, guest_r14);
             break;
 
          case 15:
-            ret = offsetof(VexGuestMIPS32State, guest_w15);
+            ret = offsetof(VexGuestMIPS64State, guest_r15);
             break;
 
          case 16:
-            ret = offsetof(VexGuestMIPS32State, guest_w16);
+            ret = offsetof(VexGuestMIPS64State, guest_r16);
             break;
 
          case 17:
-            ret = offsetof(VexGuestMIPS32State, guest_w17);
+            ret = offsetof(VexGuestMIPS64State, guest_r17);
             break;
 
          case 18:
-            ret = offsetof(VexGuestMIPS32State, guest_w18);
+            ret = offsetof(VexGuestMIPS64State, guest_r18);
             break;
 
          case 19:
-            ret = offsetof(VexGuestMIPS32State, guest_w19);
+            ret = offsetof(VexGuestMIPS64State, guest_r19);
             break;
 
          case 20:
-            ret = offsetof(VexGuestMIPS32State, guest_w20);
+            ret = offsetof(VexGuestMIPS64State, guest_r20);
             break;
 
          case 21:
-            ret = offsetof(VexGuestMIPS32State, guest_w21);
+            ret = offsetof(VexGuestMIPS64State, guest_r21);
             break;
 
          case 22:
-            ret = offsetof(VexGuestMIPS32State, guest_w22);
+            ret = offsetof(VexGuestMIPS64State, guest_r22);
             break;
 
          case 23:
-            ret = offsetof(VexGuestMIPS32State, guest_w23);
+            ret = offsetof(VexGuestMIPS64State, guest_r23);
             break;
 
          case 24:
-            ret = offsetof(VexGuestMIPS32State, guest_w24);
+            ret = offsetof(VexGuestMIPS64State, guest_r24);
             break;
 
          case 25:
-            ret = offsetof(VexGuestMIPS32State, guest_w25);
+            ret = offsetof(VexGuestMIPS64State, guest_r25);
             break;
 
          case 26:
-            ret = offsetof(VexGuestMIPS32State, guest_w26);
+            ret = offsetof(VexGuestMIPS64State, guest_r26);
             break;
 
          case 27:
-            ret = offsetof(VexGuestMIPS32State, guest_w27);
+            ret = offsetof(VexGuestMIPS64State, guest_r27);
             break;
 
          case 28:
-            ret = offsetof(VexGuestMIPS32State, guest_w28);
+            ret = offsetof(VexGuestMIPS64State, guest_r28);
             break;
 
          case 29:
-            ret = offsetof(VexGuestMIPS32State, guest_w29);
+            ret = offsetof(VexGuestMIPS64State, guest_r29);
             break;
 
          case 30:
-            ret = offsetof(VexGuestMIPS32State, guest_w30);
+            ret = offsetof(VexGuestMIPS64State, guest_r30);
             break;
 
          case 31:
-            ret = offsetof(VexGuestMIPS32State, guest_w31);
+            ret = offsetof(VexGuestMIPS64State, guest_r31);
             break;
 
          default:
             vassert(0);
             break;
       }
-   }
 
    return ret;
 }
 
-
-/* Do a endian load of a 32-bit word, regardless of the endianness of the
-   underlying host. */
-static inline UInt getUInt(const UChar * p)
-{
-   UInt w = 0;
-#if defined (_MIPSEL)
-   w = (w << 8) | p[3];
-   w = (w << 8) | p[2];
-   w = (w << 8) | p[1];
-   w = (w << 8) | p[0];
-#elif defined (_MIPSEB)
-   w = (w << 8) | p[0];
-   w = (w << 8) | p[1];
-   w = (w << 8) | p[2];
-   w = (w << 8) | p[3];
+#if defined(VGP_mips32_linux)
+#define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
+#else
+#define OFFB_PC     offsetof(VexGuestMIPS64State, guest_PC)
 #endif
-   return w;
-}
 
-#define BITS2(_b1,_b0) \
-   (((_b1) << 1) | (_b0))
+/* ---------------- Floating point registers ---------------- */
 
-#define BITS3(_b2,_b1,_b0)                      \
-  (((_b2) << 2) | ((_b1) << 1) | (_b0))
+static UInt floatGuestRegOffset(UInt fregNo)
+{
+   vassert(fregNo < 32);
+   UInt ret;
 
-#define BITS4(_b3,_b2,_b1,_b0) \
-   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
+   if (!mode64)
+      switch (fregNo) {
+         case 0:
+            ret = offsetof(VexGuestMIPS32State, guest_f0);
+            break;
 
-#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
-   (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
+         case 1:
+            ret = offsetof(VexGuestMIPS32State, guest_f1);
+            break;
 
-#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
-   ((BITS2((_b5),(_b4)) << 4) \
-    | BITS4((_b3),(_b2),(_b1),(_b0)))
+         case 2:
+            ret = offsetof(VexGuestMIPS32State, guest_f2);
+            break;
 
-#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
-   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
-    | BITS4((_b3),(_b2),(_b1),(_b0)))
+         case 3:
+            ret = offsetof(VexGuestMIPS32State, guest_f3);
+            break;
 
-#define LOAD_STORE_PATTERN \
-   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
-      if(!mode64) \
-         assign(t1, binop(Iop_Add32, getIReg(rs), \
-                                     mkU32(extend_s_16to32(imm)))); \
-      else \
-         assign(t1, binop(Iop_Add64, getIReg(rs), \
-                                     mkU64(extend_s_16to64(imm)))); \
+         case 4:
+            ret = offsetof(VexGuestMIPS32State, guest_f4);
+            break;
 
-#define LOAD_STORE_PATTERN_MSA(imm) \
-   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
-      if (!mode64) \
-         assign(t1, binop(Iop_Add32, getIReg(ws),  \
-                                     mkU32(extend_s_10to32(imm)))); \
-      else \
-         assign(t1, binop(Iop_Add64, getIReg(ws), \
-                                     mkU64(extend_s_10to64(imm)))); \
+         case 5:
+            ret = offsetof(VexGuestMIPS32State, guest_f5);
+            break;
 
-#define LOADX_STORE_PATTERN \
-   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
-      if(!mode64) \
-         assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
-      else \
-         assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
+         case 6:
+            ret = offsetof(VexGuestMIPS32State, guest_f6);
+            break;
 
-#define LWX_SWX_PATTERN64 \
-   t2 = newTemp(Ity_I64); \
-   assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
-   t4 = newTemp(Ity_I32); \
-   assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
-                                      mkexpr(t1), mkU64(0x3))));
+         case 7:
+            ret = offsetof(VexGuestMIPS32State, guest_f7);
+            break;
 
-#define LWX_SWX_PATTERN64_1 \
-   t2 = newTemp(Ity_I64); \
-   assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
-   t4 = newTemp(Ity_I64); \
-   assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+         case 8:
+            ret = offsetof(VexGuestMIPS32State, guest_f8);
+            break;
 
-#define LWX_SWX_PATTERN \
-   t2 = newTemp(Ity_I32); \
-   assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
-   t4 = newTemp(Ity_I32); \
-   assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
+         case 9:
+            ret = offsetof(VexGuestMIPS32State, guest_f9);
+            break;
 
-#define SXXV_PATTERN(op) \
-   putIReg(rd, binop(op, \
-         getIReg(rt), \
-            unop(Iop_32to8, \
-               binop(Iop_And32, \
-                  getIReg(rs), \
-                  mkU32(0x0000001F) \
-               ) \
-            ) \
-         ) \
-      )
+         case 10:
+            ret = offsetof(VexGuestMIPS32State, guest_f10);
+            break;
 
-#define SXXV_PATTERN64(op) \
-   putIReg(rd, mkWidenFrom32(ty, binop(op, \
-           mkNarrowTo32(ty, getIReg(rt)), \
-             unop(Iop_32to8, \
-                binop(Iop_And32, \
-                   mkNarrowTo32(ty, getIReg(rs)), \
-                   mkU32(0x0000001F) \
-                ) \
-             ) \
-          ), True \
-       ))
+         case 11:
+            ret = offsetof(VexGuestMIPS32State, guest_f11);
+            break;
 
-#define SXX_PATTERN(op) \
-   putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
+         case 12:
+            ret = offsetof(VexGuestMIPS32State, guest_f12);
+            break;
 
-#define ALU_PATTERN(op) \
-   putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
+         case 13:
+            ret = offsetof(VexGuestMIPS32State, guest_f13);
+            break;
 
-#define ALUI_PATTERN(op) \
-   putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
+         case 14:
+            ret = offsetof(VexGuestMIPS32State, guest_f14);
+            break;
 
-#define ALUI_PATTERN64(op) \
-   putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
+         case 15:
+            ret = offsetof(VexGuestMIPS32State, guest_f15);
+            break;
 
-#define ALU_PATTERN64(op) \
-   putIReg(rd, mkWidenFrom32(ty, binop(op, \
-                             mkNarrowTo32(ty, getIReg(rs)), \
-                             mkNarrowTo32(ty, getIReg(rt))), True));
+         case 16:
+            ret = offsetof(VexGuestMIPS32State, guest_f16);
+            break;
 
-#define FP_CONDITIONAL_CODE \
-   t3 = newTemp(Ity_I32);   \
-   assign(t3, binop(Iop_And32, \
-                 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
-                             binop(Iop_Shr32, getFCSR(), mkU8(23)), \
-                             binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
-                 mkU32(0x1)));
+         case 17:
+            ret = offsetof(VexGuestMIPS32State, guest_f17);
+            break;
 
-#define ILLEGAL_INSTRUCTON \
-   putPC(mkU32(guest_PC_curr_instr + 4)); \
-   dres.jk_StopHere = Ijk_SigILL; \
-   dres.whatNext    = Dis_StopHere;
+         case 18:
+            ret = offsetof(VexGuestMIPS32State, guest_f18);
+            break;
 
-#define LLADDR_INVALID \
-   (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
+         case 19:
+            ret = offsetof(VexGuestMIPS32State, guest_f19);
+            break;
 
-/*------------------------------------------------------------*/
-/*---                  Field helpers                       ---*/
-/*------------------------------------------------------------*/
+         case 20:
+            ret = offsetof(VexGuestMIPS32State, guest_f20);
+            break;
 
-static UInt get_opcode(UInt mipsins)
-{
-   return (0xFC000000 & mipsins) >> 26;
-}
+         case 21:
+            ret = offsetof(VexGuestMIPS32State, guest_f21);
+            break;
 
-static UInt get_rs(UInt mipsins)
-{
-   return (0x03E00000 & mipsins) >> 21;
-}
+         case 22:
+            ret = offsetof(VexGuestMIPS32State, guest_f22);
+            break;
 
-static UInt get_rt(UInt mipsins)
-{
-   return (0x001F0000 & mipsins) >> 16;
-}
+         case 23:
+            ret = offsetof(VexGuestMIPS32State, guest_f23);
+            break;
 
-static UInt get_imm(UInt mipsins)
-{
-   return (0x0000FFFF & mipsins);
-}
+         case 24:
+            ret = offsetof(VexGuestMIPS32State, guest_f24);
+            break;
 
-static UInt get_instr_index(UInt mipsins)
-{
-   return (0x03FFFFFF & mipsins);
-}
+         case 25:
+            ret = offsetof(VexGuestMIPS32State, guest_f25);
+            break;
 
-static UInt get_rd(UInt mipsins)
-{
-   return (0x0000F800 & mipsins) >> 11;
-}
+         case 26:
+            ret = offsetof(VexGuestMIPS32State, guest_f26);
+            break;
 
-static UInt get_sa(UInt mipsins)
-{
-   return (0x000007C0 & mipsins) >> 6;
-}
+         case 27:
+            ret = offsetof(VexGuestMIPS32State, guest_f27);
+            break;
 
-static UInt get_function(UInt mipsins)
-{
-   return (0x0000003F & mipsins);
-}
+         case 28:
+            ret = offsetof(VexGuestMIPS32State, guest_f28);
+            break;
 
-static UInt get_ft(UInt mipsins)
-{
-   return (0x001F0000 & mipsins) >> 16;
-}
+         case 29:
+            ret = offsetof(VexGuestMIPS32State, guest_f29);
+            break;
 
-static UInt get_fs(UInt mipsins)
-{
-   return (0x0000F800 & mipsins) >> 11;
-}
+         case 30:
+            ret = offsetof(VexGuestMIPS32State, guest_f30);
+            break;
 
-static UInt get_fd(UInt mipsins)
-{
-   return (0x000007C0 & mipsins) >> 6;
-}
+         case 31:
+            ret = offsetof(VexGuestMIPS32State, guest_f31);
+            break;
 
-static UInt get_mov_cc(UInt mipsins)
-{
-   return (0x001C0000 & mipsins) >> 18;
-}
+         default:
+            vassert(0);
+            break;
+      }
+   else
+      switch (fregNo) {
+         case 0:
+            ret = offsetof(VexGuestMIPS64State, guest_f0);
+            break;
 
-static UInt get_bc1_cc(UInt mipsins)
-{
-   return (0x001C0000 & mipsins) >> 18;
-}
+         case 1:
+            ret = offsetof(VexGuestMIPS64State, guest_f1);
+            break;
 
-static UInt get_fpc_cc(UInt mipsins)
-{
-   return (0x00000700 & mipsins) >> 8;
-}
+         case 2:
+            ret = offsetof(VexGuestMIPS64State, guest_f2);
+            break;
 
-static UInt get_tf(UInt mipsins)
-{
-   return (0x00010000 & mipsins) >> 16;
-}
+         case 3:
+            ret = offsetof(VexGuestMIPS64State, guest_f3);
+            break;
 
-static UInt get_nd(UInt mipsins)
-{
-   return (0x00020000 & mipsins) >> 17;
-}
+         case 4:
+            ret = offsetof(VexGuestMIPS64State, guest_f4);
+            break;
 
-static UInt get_fmt(UInt mipsins)
-{
-   return (0x03E00000 & mipsins) >> 21;
-}
+         case 5:
+            ret = offsetof(VexGuestMIPS64State, guest_f5);
+            break;
 
-static UInt get_FC(UInt mipsins)
-{
-   return (0x000000F0 & mipsins) >> 4;
-}
+         case 6:
+            ret = offsetof(VexGuestMIPS64State, guest_f6);
+            break;
 
-static UInt get_cond(UInt mipsins)
-{
-   return (0x0000000F & mipsins);
-}
+         case 7:
+            ret = offsetof(VexGuestMIPS64State, guest_f7);
+            break;
 
-/* for break & syscall */
-static UInt get_code(UInt mipsins)
-{
-   return (0xFFC0 & mipsins) >> 6;
-}
+         case 8:
+            ret = offsetof(VexGuestMIPS64State, guest_f8);
+            break;
 
-static UInt get_lsb(UInt mipsins)
-{
-   return (0x7C0 & mipsins) >> 6;
-}
+         case 9:
+            ret = offsetof(VexGuestMIPS64State, guest_f9);
+            break;
 
-static UInt get_msb(UInt mipsins)
-{
-   return (0x0000F800 & mipsins) >> 11;
-}
+         case 10:
+            ret = offsetof(VexGuestMIPS64State, guest_f10);
+            break;
 
-static UInt get_rot(UInt mipsins)
-{
-   return (0x00200000 & mipsins) >> 21;
-}
+         case 11:
+            ret = offsetof(VexGuestMIPS64State, guest_f11);
+            break;
 
-static UInt get_rotv(UInt mipsins)
-{
-   return (0x00000040 & mipsins) >> 6;
-}
+         case 12:
+            ret = offsetof(VexGuestMIPS64State, guest_f12);
+            break;
 
-static UInt get_sel(UInt mipsins)
-{
-   return (0x00000007 & mipsins);
-}
+         case 13:
+            ret = offsetof(VexGuestMIPS64State, guest_f13);
+            break;
 
-/* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
-   except for MFHI and MFLO. */
-static UInt get_acNo(UInt mipsins)
-{
-   return (0x00001800 & mipsins) >> 11;
-}
+         case 14:
+            ret = offsetof(VexGuestMIPS64State, guest_f14);
+            break;
 
-/* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
-static UInt get_acNo_mfhilo(UInt mipsins)
-{
-   return (0x00600000 & mipsins) >> 21;
-}
+         case 15:
+            ret = offsetof(VexGuestMIPS64State, guest_f15);
+            break;
 
-/* Get mask field (helper function for wrdsp instruction). */
-static UInt get_wrdspMask(UInt mipsins)
-{
-   return (0x001ff800 & mipsins) >> 11;
-}
+         case 16:
+            ret = offsetof(VexGuestMIPS64State, guest_f16);
+            break;
 
-/* Get mask field (helper function for rddsp instruction). */
-static UInt get_rddspMask(UInt mipsins)
-{
-   return (0x03ff0000 & mipsins) >> 16;
-}
+         case 17:
+            ret = offsetof(VexGuestMIPS64State, guest_f17);
+            break;
 
-/* Get shift field (helper function for DSP ASE instructions). */
-static UInt get_shift(UInt mipsins)
-{
-   return (0x03f00000 & mipsins) >> 20;
-}
+         case 18:
+            ret = offsetof(VexGuestMIPS64State, guest_f18);
+            break;
 
-/* Get immediate field for DSP ASE instructions. */
-static UInt get_dspImm(UInt mipsins)
-{
-   return (0x03ff0000 & mipsins) >> 16;
-}
+         case 19:
+            ret = offsetof(VexGuestMIPS64State, guest_f19);
+            break;
 
-static Bool branch_or_jump(const UChar * addr)
-{
-   UInt fmt;
-   UInt cins = getUInt(addr);
+         case 20:
+            ret = offsetof(VexGuestMIPS64State, guest_f20);
+            break;
 
-   UInt opcode = get_opcode(cins);
-   UInt rt = get_rt(cins);
-   UInt function = get_function(cins);
+         case 21:
+            ret = offsetof(VexGuestMIPS64State, guest_f21);
+            break;
 
-   /* bgtz, blez, bne, beq, jal */
-   if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
-       || opcode == 0x03 || opcode == 0x02) {
-      return True;
-   }
+         case 22:
+            ret = offsetof(VexGuestMIPS64State, guest_f22);
+            break;
 
-   /* bgez */
-   if (opcode == 0x01 && rt == 0x01) {
-      return True;
-   }
+         case 23:
+            ret = offsetof(VexGuestMIPS64State, guest_f23);
+            break;
 
-   /* bgezal */
-   if (opcode == 0x01 && rt == 0x11) {
-      return True;
-   }
+         case 24:
+            ret = offsetof(VexGuestMIPS64State, guest_f24);
+            break;
 
-   /* bltzal */
-   if (opcode == 0x01 && rt == 0x10) {
-      return True;
-   }
+         case 25:
+            ret = offsetof(VexGuestMIPS64State, guest_f25);
+            break;
 
-   /* bltz */
-   if (opcode == 0x01 && rt == 0x00) {
-      return True;
-   }
+         case 26:
+            ret = offsetof(VexGuestMIPS64State, guest_f26);
+            break;
 
-   /* jalr */
-   if (opcode == 0x00 && function == 0x09) {
-      return True;
-   }
+         case 27:
+            ret = offsetof(VexGuestMIPS64State, guest_f27);
+            break;
 
-   /* jr */
-   if (opcode == 0x00 && function == 0x08) {
-      return True;
-   }
+         case 28:
+            ret = offsetof(VexGuestMIPS64State, guest_f28);
+            break;
 
-   if (opcode == 0x11) {
-      /* bc1f & bc1t */
-      fmt = get_fmt(cins);
-      if (fmt == 0x08) {
-         return True;
-      }
+         case 29:
+            ret = offsetof(VexGuestMIPS64State, guest_f29);
+            break;
 
-      /* MSA branches */
-      /* bnz.df, bz.df */
-      if (fmt >= 0x18) {
-         return True;
-      }
-      /* bnz.v */
-      if (fmt == 0x0f) {
-         return True;
-      }
-      /* bz.v */
-      if (fmt == 0x0b) {
-         return True;
-      }
+         case 30:
+            ret = offsetof(VexGuestMIPS64State, guest_f30);
+            break;
 
-      /* R6 branches */
-      /* bc1eqz */
-      if (fmt == 0x09) {
-         return True;
-      }
+         case 31:
+            ret = offsetof(VexGuestMIPS64State, guest_f31);
+            break;
 
-      /* bc1nez */
-      if (fmt == 0x0D) {
-         return True;
+         default:
+            vassert(0);
+            break;
       }
-   }
-
-   /* bposge32 */
-   if (opcode == 0x01 && rt == 0x1c) {
-      return True;
-   }
-
-   /* Cavium Specific instructions. */
-   if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
-       /* BBIT0, BBIT1, BBIT032, BBIT132 */
-      return True;
-   }
 
-   return False;
+   return ret;
 }
 
-static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
+/* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
+
+UInt accumulatorGuestRegOffset(UInt acNo)
 {
-   UInt cins = getUInt(addr);
+   vassert(!mode64);
+   vassert(acNo <= 3);
+   UInt ret;
 
-   UInt opcode = get_opcode(cins);
-   UInt rt = get_rt(cins);
-   UInt function = get_function(cins);
+   switch (acNo) {
+      case 0:
+         ret = offsetof(VexGuestMIPS32State, guest_ac0);
+         break;
 
-   /* jal */
-   if (opcode == 0x02) {
-      return True;
-   }
+      case 1:
+         ret = offsetof(VexGuestMIPS32State, guest_ac1);
+         break;
 
-   /* bgezal or bal(r6) */
-   if (opcode == 0x01 && rt == 0x11) {
-      return True;
-   }
+      case 2:
+         ret = offsetof(VexGuestMIPS32State, guest_ac2);
+         break;
 
-   /* bltzal */
-   if (opcode == 0x01 && rt == 0x10) {
-      return True;
-   }
+      case 3:
+         ret = offsetof(VexGuestMIPS32State, guest_ac3);
+         break;
 
-   /* jalr */
-   if (opcode == 0x00 && function == 0x09) {
-      return True;
+      default:
+         vassert(0);
+         break;
    }
 
-   return False;
+   return ret;
 }
 
-static Bool branch_or_link_likely(const UChar * addr)
-{
-   UInt cins = getUInt(addr);
-   UInt opcode = get_opcode(cins);
-   UInt rt = get_rt(cins);
+/* ---------------- MIPS32 MSA registers ---------------- */
 
-   /* bgtzl, blezl, bnel, beql */
-   if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
-      return True;
+static UInt msaGuestRegOffset(UInt msaRegNo)
+{
+   vassert(msaRegNo <= 31);
+   UInt ret;
 
-   /* bgezl */
-   if (opcode == 0x01 && rt == 0x03)
-      return True;
+   if (mode64) {
+      switch (msaRegNo) {
+         case 0:
+            ret = offsetof(VexGuestMIPS64State, guest_w0);
+            break;
 
-   /* bgezall */
-   if (opcode == 0x01 && rt == 0x13)
-      return True;
+         case 1:
+            ret = offsetof(VexGuestMIPS64State, guest_w1);
+            break;
 
-   /* bltzall */
-   if (opcode == 0x01 && rt == 0x12)
-      return True;
+         case 2:
+            ret = offsetof(VexGuestMIPS64State, guest_w2);
+            break;
 
-   /* bltzl */
-   if (opcode == 0x01 && rt == 0x02)
-      return True;
+         case 3:
+            ret = offsetof(VexGuestMIPS64State, guest_w3);
+            break;
 
-   return False;
-}
+         case 4:
+            ret = offsetof(VexGuestMIPS64State, guest_w4);
+            break;
 
-/*------------------------------------------------------------*/
-/*--- Helper bits and pieces for creating IR fragments.    ---*/
-/*------------------------------------------------------------*/
+         case 5:
+            ret = offsetof(VexGuestMIPS64State, guest_w5);
+            break;
 
-static IRExpr *mkU8(UInt i)
-{
-   vassert(i < 256);
-   return IRExpr_Const(IRConst_U8((UChar) i));
-}
+         case 6:
+            ret = offsetof(VexGuestMIPS64State, guest_w6);
+            break;
 
-/* Create an expression node for a 16-bit integer constant. */
-static IRExpr *mkU16(UInt i)
-{
-   return IRExpr_Const(IRConst_U16(i));
-}
+         case 7:
+            ret = offsetof(VexGuestMIPS64State, guest_w7);
+            break;
 
-/* Create an expression node for a 32-bit integer constant. */
-static IRExpr *mkU32(UInt i)
-{
-   return IRExpr_Const(IRConst_U32(i));
-}
+         case 8:
+            ret = offsetof(VexGuestMIPS64State, guest_w8);
+            break;
 
-/* Create an expression node for a 64-bit integer constant. */
-static IRExpr *mkU64(ULong i)
-{
-   return IRExpr_Const(IRConst_U64(i));
-}
+         case 9:
+            ret = offsetof(VexGuestMIPS64State, guest_w9);
+            break;
 
-static IRExpr *mkexpr(IRTemp tmp)
-{
-   return IRExpr_RdTmp(tmp);
-}
+         case 10:
+            ret = offsetof(VexGuestMIPS64State, guest_w10);
+            break;
 
-static IRExpr *unop(IROp op, IRExpr * a)
-{
-   return IRExpr_Unop(op, a);
-}
+         case 11:
+            ret = offsetof(VexGuestMIPS64State, guest_w11);
+            break;
 
-static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
-{
-   return IRExpr_Binop(op, a1, a2);
-}
+         case 12:
+            ret = offsetof(VexGuestMIPS64State, guest_w12);
+            break;
 
-static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
-{
-   return IRExpr_Triop(op, a1, a2, a3);
-}
+         case 13:
+            ret = offsetof(VexGuestMIPS64State, guest_w13);
+            break;
 
-static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
-                     IRExpr * a4 )
-{
-   return IRExpr_Qop(op, a1, a2, a3, a4);
-}
+         case 14:
+            ret = offsetof(VexGuestMIPS64State, guest_w14);
+            break;
 
-static IRExpr *load(IRType ty, IRExpr * addr)
-{
-   IRExpr *load1 = NULL;
-#if defined (_MIPSEL)
-   load1 = IRExpr_Load(Iend_LE, ty, addr);
-#elif defined (_MIPSEB)
-   load1 = IRExpr_Load(Iend_BE, ty, addr);
-#endif
-   return load1;
-}
+         case 15:
+            ret = offsetof(VexGuestMIPS64State, guest_w15);
+            break;
 
-/* Add a statement to the list held by "irsb". */
-static void stmt(IRStmt * st)
-{
-   addStmtToIRSB(irsb, st);
-}
+         case 16:
+            ret = offsetof(VexGuestMIPS64State, guest_w16);
+            break;
 
-static void assign(IRTemp dst, IRExpr * e)
-{
-   stmt(IRStmt_WrTmp(dst, e));
-}
+         case 17:
+            ret = offsetof(VexGuestMIPS64State, guest_w17);
+            break;
 
-static void store(IRExpr * addr, IRExpr * data)
-{
-#if defined (_MIPSEL)
-   stmt(IRStmt_Store(Iend_LE, addr, data));
-#elif defined (_MIPSEB)
-   stmt(IRStmt_Store(Iend_BE, addr, data));
-#endif
-}
+         case 18:
+            ret = offsetof(VexGuestMIPS64State, guest_w18);
+            break;
 
-/* Generate a new temporary of the given type. */
-static IRTemp newTemp(IRType ty)
-{
-   vassert(isPlausibleIRType(ty));
-   return newIRTemp(irsb->tyenv, ty);
-}
+         case 19:
+            ret = offsetof(VexGuestMIPS64State, guest_w19);
+            break;
 
-/* Generate an expression for SRC rotated right by ROT. */
-static IRExpr *genROR32(IRExpr * src, Int rot)
-{
-   vassert(rot >= 0 && rot < 32);
-   if (rot == 0)
-      return src;
-   return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
-                          binop(Iop_Shr32, src, mkU8(rot)));
-}
+         case 20:
+            ret = offsetof(VexGuestMIPS64State, guest_w20);
+            break;
 
-static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
-{
-   IRTemp t0 = newTemp(Ity_I8);
-   IRTemp t1 = newTemp(Ity_I8);
+         case 21:
+            ret = offsetof(VexGuestMIPS64State, guest_w21);
+            break;
 
-   assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
-   assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
-   return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
-                          binop(Iop_Shr32, src, mkexpr(t0)));
-}
+         case 22:
+            ret = offsetof(VexGuestMIPS64State, guest_w22);
+            break;
 
+         case 23:
+            ret = offsetof(VexGuestMIPS64State, guest_w23);
+            break;
 
-static UShort extend_s_9to16(UInt x)
-{
-   return (UShort) ((((Int) x) << 23) >> 23);
-}
+         case 24:
+            ret = offsetof(VexGuestMIPS64State, guest_w24);
+            break;
 
-static UShort extend_s_10to16(UInt x)
-{
-   return (UShort) ((((Int) x) << 22) >> 22);
-}
+         case 25:
+            ret = offsetof(VexGuestMIPS64State, guest_w25);
+            break;
 
-static UInt extend_s_10to32(UInt x)
-{
-   return (UInt)((((Int) x) << 22) >> 22);
-}
+         case 26:
+            ret = offsetof(VexGuestMIPS64State, guest_w26);
+            break;
 
-static ULong extend_s_10to64(UInt x)
-{
-   return (ULong)((((Long) x) << 54) >> 54);
-}
+         case 27:
+            ret = offsetof(VexGuestMIPS64State, guest_w27);
+            break;
 
-static UInt extend_s_16to32(UInt x)
-{
-   return (UInt) ((((Int) x) << 16) >> 16);
-}
+         case 28:
+            ret = offsetof(VexGuestMIPS64State, guest_w28);
+            break;
 
-static UInt extend_s_18to32(UInt x)
-{
-   return (UInt) ((((Int) x) << 14) >> 14);
-}
+         case 29:
+            ret = offsetof(VexGuestMIPS64State, guest_w29);
+            break;
 
-static UInt extend_s_19to32(UInt x)
-{
-   return (UInt) ((((Int) x) << 13) >> 13);
-}
+         case 30:
+            ret = offsetof(VexGuestMIPS64State, guest_w30);
+            break;
 
-static UInt extend_s_23to32(UInt x)
-{
-   return (UInt) ((((Int) x) << 9) >> 9);
-}
+         case 31:
+            ret = offsetof(VexGuestMIPS64State, guest_w31);
+            break;
 
-static UInt extend_s_26to32(UInt x)
-{
-   return (UInt) ((((Int) x) << 6) >> 6);
-}
+         default:
+            vassert(0);
+            break;
+      }
+   } else {
+      switch (msaRegNo) {
+         case 0:
+            ret = offsetof(VexGuestMIPS32State, guest_w0);
+            break;
 
-static ULong extend_s_16to64 ( UInt x )
-{
-   return (ULong) ((((Long) x) << 48) >> 48);
-}
+         case 1:
+            ret = offsetof(VexGuestMIPS32State, guest_w1);
+            break;
 
-static ULong extend_s_18to64 ( UInt x )
-{
-   return (ULong) ((((Long) x) << 46) >> 46);
-}
+         case 2:
+            ret = offsetof(VexGuestMIPS32State, guest_w2);
+            break;
 
-static ULong extend_s_19to64(UInt x)
-{
-   return (ULong) ((((Long) x) << 45) >> 45);
-}
+         case 3:
+            ret = offsetof(VexGuestMIPS32State, guest_w3);
+            break;
 
-static ULong extend_s_23to64(UInt x)
-{
-   return (ULong) ((((Long) x) << 41) >> 41);
-}
+         case 4:
+            ret = offsetof(VexGuestMIPS32State, guest_w4);
+            break;
 
-static ULong extend_s_26to64(UInt x)
-{
-   return (ULong) ((((Long) x) << 38) >> 38);
-}
+         case 5:
+            ret = offsetof(VexGuestMIPS32State, guest_w5);
+            break;
 
-static ULong extend_s_32to64 ( UInt x )
-{
-   return (ULong) ((((Long) x) << 32) >> 32);
-}
+         case 6:
+            ret = offsetof(VexGuestMIPS32State, guest_w6);
+            break;
 
-static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
-{
-   vassert(dres->whatNext    == Dis_Continue);
-   vassert(dres->len         == 0);
-   vassert(dres->continueAt  == 0);
-   vassert(dres->jk_StopHere == Ijk_INVALID);
-   dres->whatNext    = Dis_StopHere;
-   dres->jk_StopHere = kind;
-   stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
-}
+         case 7:
+            ret = offsetof(VexGuestMIPS32State, guest_w7);
+            break;
 
-static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
-{
-   vassert(dres->whatNext    == Dis_Continue);
-   vassert(dres->len         == 0);
-   vassert(dres->continueAt  == 0);
-   vassert(dres->jk_StopHere == Ijk_INVALID);
-   dres->whatNext    = Dis_StopHere;
-   dres->jk_StopHere = kind;
-   stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
-}
+         case 8:
+            ret = offsetof(VexGuestMIPS32State, guest_w8);
+            break;
 
-/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
-   This function should be called before any other operation if widening
-   multiplications are used. */
-static IRExpr *getAcc(UInt acNo)
-{
-   vassert(!mode64);
-   vassert(acNo <= 3);
-   return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
-}
+         case 9:
+            ret = offsetof(VexGuestMIPS32State, guest_w9);
+            break;
 
-/* Get value from DSPControl register (helper function for MIPS32 DSP ASE
-   instructions). */
-static IRExpr *getDSPControl(void)
-{
-   vassert(!mode64);
-   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
-}
+         case 10:
+            ret = offsetof(VexGuestMIPS32State, guest_w10);
+            break;
 
-/* Put value to DSPControl register. Expression e is written to DSPControl as
-   is. If only certain bits of DSPControl need to be changed, it should be done
-   before calling putDSPControl(). It could be done by reading DSPControl and
-   ORing it with appropriate mask. */
-static void putDSPControl(IRExpr * e)
-{
-   vassert(!mode64);
-   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
-}
+         case 11:
+            ret = offsetof(VexGuestMIPS32State, guest_w11);
+            break;
 
-/* Fetch a byte from the guest insn stream. */
-static UChar getIByte(Int delta)
-{
-   return guest_code[delta];
-}
+         case 12:
+            ret = offsetof(VexGuestMIPS32State, guest_w12);
+            break;
 
-static IRExpr *getIReg(UInt iregNo)
-{
-   if (0 == iregNo) {
-      return mode64 ? mkU64(0x0) : mkU32(0x0);
-   } else {
-      IRType ty = mode64 ? Ity_I64 : Ity_I32;
-      vassert(iregNo < 32);
-      return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
-   }
-}
+         case 13:
+            ret = offsetof(VexGuestMIPS32State, guest_w13);
+            break;
 
+         case 14:
+            ret = offsetof(VexGuestMIPS32State, guest_w14);
+            break;
 
-static IRExpr *getWReg(UInt wregNo) {
-   vassert(wregNo <= 31);
-   return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
-}
+         case 15:
+            ret = offsetof(VexGuestMIPS32State, guest_w15);
+            break;
 
-static IRExpr *getHI(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
-}
+         case 16:
+            ret = offsetof(VexGuestMIPS32State, guest_w16);
+            break;
 
-static IRExpr *getLO(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
-}
+         case 17:
+            ret = offsetof(VexGuestMIPS32State, guest_w17);
+            break;
 
-static IRExpr *getFCSR(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
-}
+         case 18:
+            ret = offsetof(VexGuestMIPS32State, guest_w18);
+            break;
 
-static IRExpr *getLLaddr(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
-}
+         case 19:
+            ret = offsetof(VexGuestMIPS32State, guest_w19);
+            break;
 
-static IRExpr *getLLdata(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
-}
+         case 20:
+            ret = offsetof(VexGuestMIPS32State, guest_w20);
+            break;
 
-static IRExpr *getMSACSR(void) {
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
-}
+         case 21:
+            ret = offsetof(VexGuestMIPS32State, guest_w21);
+            break;
 
-/* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
-static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
-{
-  UInt pos = byte_pos * 8;
-  if (mode64)
-      return unop(Iop_64to8, binop(Iop_And64,
-                                   binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
-                                   mkU64(0xFF)));
-   else
-      return unop(Iop_32to8, binop(Iop_And32,
-                                   binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
-                                   mkU32(0xFF)));
-}
+         case 22:
+            ret = offsetof(VexGuestMIPS32State, guest_w22);
+            break;
 
-static void putFCSR(IRExpr * e)
-{
-   if (mode64)
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
-   else
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
-}
+         case 23:
+            ret = offsetof(VexGuestMIPS32State, guest_w23);
+            break;
 
-static void putLLaddr(IRExpr * e)
-{
-   if (mode64)
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
-   else
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
-}
+         case 24:
+            ret = offsetof(VexGuestMIPS32State, guest_w24);
+            break;
 
-static void putLLdata(IRExpr * e)
-{
-   if (mode64)
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
-   else
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
-}
+         case 25:
+            ret = offsetof(VexGuestMIPS32State, guest_w25);
+            break;
 
-static void putMSACSR(IRExpr * e) {
-   if (mode64)
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
-   else
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
-}
+         case 26:
+            ret = offsetof(VexGuestMIPS32State, guest_w26);
+            break;
 
-/* fs   - fpu source register number.
-   inst - fpu instruction that needs to be executed.
-   sz32 - size of source register.
-   opN  - number of operads:
-          1 - unary operation.
-          2 - binary operation. */
-static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
-{
-   IRDirty *d;
-   IRTemp fcsr = newTemp(Ity_I32);
-   /* IRExpr_GSPTR() => 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_GSPTR(),
-                                          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_GSPTR(),
-                                          mkU32(fs),
-                                          mkU32(ft),
-                                          mkU32(inst)));
+         case 27:
+            ret = offsetof(VexGuestMIPS32State, guest_w27);
+            break;
 
-   if (opN == 1) {  /* Unary operation. */
-      /* Declare we're reading guest state. */
-      if (sz32 || fp_mode64)
-         d->nFxState = 2;
-      else
-         d->nFxState = 3;
-      vex_bzero(&d->fxState, sizeof(d->fxState));
+         case 28:
+            ret = offsetof(VexGuestMIPS32State, guest_w28);
+            break;
 
-      d->fxState[0].fx     = Ifx_Read;  /* read */
-      if (mode64)
-         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
-      else
-         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
-      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);
+         case 29:
+            ret = offsetof(VexGuestMIPS32State, guest_w29);
+            break;
 
-      if (!(sz32 || fp_mode64)) {
-         d->fxState[2].fx     = Ifx_Read;  /* read */
-         d->fxState[2].offset = floatGuestRegOffset(fs+1);
-         d->fxState[2].size   = sizeof(ULong);
-      }
-   } else if (opN == 2) {  /* Binary operation. */
-      /* Declare we're reading guest state. */
-      if (sz32 || fp_mode64)
-         d->nFxState = 3;
-      else
-         d->nFxState = 5;
-      vex_bzero(&d->fxState, sizeof(d->fxState));
+         case 30:
+            ret = offsetof(VexGuestMIPS32State, guest_w30);
+            break;
 
-      d->fxState[0].fx     = Ifx_Read;  /* read */
-      if (mode64)
-         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
-      else
-         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
-      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);
-      d->fxState[2].size   = sizeof(ULong);
+         case 31:
+            ret = offsetof(VexGuestMIPS32State, guest_w31);
+            break;
 
-      if (!(sz32 || fp_mode64)) {
-         d->fxState[3].fx     = Ifx_Read;  /* read */
-         d->fxState[3].offset = floatGuestRegOffset(fs+1);
-         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(ULong);
+         default:
+            vassert(0);
+            break;
       }
    }
 
-   stmt(IRStmt_Dirty(d));
+   return ret;
+}
 
-   putFCSR(mkexpr(fcsr));
+
+/* Do a endian load of a 32-bit word, regardless of the endianness of the
+   underlying host. */
+static inline UInt getUInt(const UChar * p)
+{
+   UInt w = 0;
+#if defined (_MIPSEL)
+   w = (w << 8) | p[3];
+   w = (w << 8) | p[2];
+   w = (w << 8) | p[1];
+   w = (w << 8) | p[0];
+#elif defined (_MIPSEB)
+   w = (w << 8) | p[0];
+   w = (w << 8) | p[1];
+   w = (w << 8) | p[2];
+   w = (w << 8) | p[3];
+#endif
+   return w;
 }
 
-/* ws, wt - source MSA register numbers.
-   inst   - MSA fp instruction that needs to be executed.
-   opN    - number of operads:
-             1 - unary operation.
-             2 - binary operation. */
-static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN) {
-   IRDirty *d;
-   IRTemp msacsr = newTemp(Ity_I32);
-   /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
-   d = unsafeIRDirty_1_N(msacsr, 0,
-                         "mips_dirtyhelper_calculate_MSACSR",
-                         &mips_dirtyhelper_calculate_MSACSR,
-                         mkIRExprVec_4(IRExpr_GSPTR(),
-                                       mkU32(ws),
-                                       mkU32(wt),
-                                       mkU32(inst)));
+#define BITS2(_b1,_b0) \
+   (((_b1) << 1) | (_b0))
 
-   if (opN == 1) {  /* Unary operation. */
-      /* Declare we're reading guest state. */
-      d->nFxState = 2;
-      vex_bzero(&d->fxState, sizeof(d->fxState));
-      d->fxState[0].fx     = Ifx_Read;  /* read */
+#define BITS3(_b2,_b1,_b0)                      \
+  (((_b2) << 2) | ((_b1) << 1) | (_b0))
 
-      if (mode64)
-         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
-      else
-         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+#define BITS4(_b3,_b2,_b1,_b0) \
+   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
 
-      d->fxState[0].size   = sizeof(UInt);
-      d->fxState[1].fx     = Ifx_Read;  /* read */
-      d->fxState[1].offset = msaGuestRegOffset(ws);
-      d->fxState[1].size   = sizeof(ULong);
-   } else if (opN == 2) {  /* Binary operation. */
-      /* Declare we're reading guest state. */
-      d->nFxState = 3;
-      vex_bzero(&d->fxState, sizeof(d->fxState));
-      d->fxState[0].fx     = Ifx_Read;  /* read */
+#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
+   (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
 
-      if (mode64)
-         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
-      else
-         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
+   ((BITS2((_b5),(_b4)) << 4) \
+    | BITS4((_b3),(_b2),(_b1),(_b0)))
 
-      d->fxState[0].size   = sizeof(UInt);
-      d->fxState[1].fx     = Ifx_Read;  /* read */
-      d->fxState[1].offset = msaGuestRegOffset(ws);
-      d->fxState[1].size   = sizeof(ULong);
-      d->fxState[2].fx     = Ifx_Read;  /* read */
-      d->fxState[2].offset = msaGuestRegOffset(wt);
-      d->fxState[2].size   = sizeof(ULong);
-   }
+#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
+   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
+    | BITS4((_b3),(_b2),(_b1),(_b0)))
 
-   stmt(IRStmt_Dirty(d));
-   putMSACSR(mkexpr(msacsr));
-}
+#define LOAD_STORE_PATTERN \
+   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+      if(!mode64) \
+         assign(t1, binop(Iop_Add32, getIReg(rs), \
+                                     mkU32(extend_s_16to32(imm)))); \
+      else \
+         assign(t1, binop(Iop_Add64, getIReg(rs), \
+                                     mkU64(extend_s_16to64(imm)))); \
 
-static IRExpr *getULR(void)
-{
-   if (mode64)
-      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
-   else
-      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
-}
+#define LOAD_STORE_PATTERN_MSA(imm) \
+   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+      if (!mode64) \
+         assign(t1, binop(Iop_Add32, getIReg(ws),  \
+                                     mkU32(extend_s_10to32(imm)))); \
+      else \
+         assign(t1, binop(Iop_Add64, getIReg(ws), \
+                                     mkU64(extend_s_10to64(imm)))); \
 
-static void putIReg(UInt archreg, IRExpr * e)
-{
-   IRType ty = mode64 ? Ity_I64 : Ity_I32;
-   vassert(archreg < 32);
-   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
-   if (archreg != 0)
-      stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
-}
+#define LOADX_STORE_PATTERN \
+   t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+      if(!mode64) \
+         assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
+      else \
+         assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
 
-static void putWReg(UInt wregNo, IRExpr * e) {
-   vassert(wregNo <= 31);
-   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
-   stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
-   stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
-                   unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
-}
+#define LWX_SWX_PATTERN64 \
+   t2 = newTemp(Ity_I64); \
+   assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
+   t4 = newTemp(Ity_I32); \
+   assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
+                                      mkexpr(t1), mkU64(0x3))));
 
-static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
-{
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
-}
+#define LWX_SWX_PATTERN64_1 \
+   t2 = newTemp(Ity_I64); \
+   assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
+   t4 = newTemp(Ity_I64); \
+   assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
 
-static void putLO(IRExpr * e)
-{
-   if (mode64) {
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
-   } else {
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
-   /* Add value to lower 32 bits of ac0 to maintain compatibility between
-      regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
-      unchanged. */
-      IRTemp t_lo = newTemp(Ity_I32);
-      IRTemp t_hi = newTemp(Ity_I32);
-      assign(t_lo, e);
-      assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
-      stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
-           binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
-   }
-}
+#define LWX_SWX_PATTERN \
+   t2 = newTemp(Ity_I32); \
+   assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
+   t4 = newTemp(Ity_I32); \
+   assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
 
-static void putHI(IRExpr * e)
-{
-   if (mode64) {
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
-   } else {
-      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
-   /* Add value to higher 32 bits of ac0 to maintain compatibility between
-      regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
-      unchanged. */
-      IRTemp t_lo = newTemp(Ity_I32);
-      IRTemp t_hi = newTemp(Ity_I32);
-      assign(t_hi, e);
-      assign(t_lo, unop(Iop_64to32, getAcc(0)));
-      stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
-           binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
-   }
-}
+#define SXXV_PATTERN(op) \
+   putIReg(rd, binop(op, \
+         getIReg(rt), \
+            unop(Iop_32to8, \
+               binop(Iop_And32, \
+                  getIReg(rs), \
+                  mkU32(0x0000001F) \
+               ) \
+            ) \
+         ) \
+      )
 
-/* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
-static void putAcc(UInt acNo, IRExpr * e)
-{
-   vassert(!mode64);
-   vassert(acNo <= 3);
-   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
-   stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
-/* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
-   between MIPS32 and MIPS DSP ASE insn sets. */
-   if (0 == acNo) {
-     putLO(unop(Iop_64to32, e));
-     putHI(unop(Iop_64HIto32, e));
-   }
-}
+#define SXXV_PATTERN64(op) \
+   putIReg(rd, mkWidenFrom32(ty, binop(op, \
+           mkNarrowTo32(ty, getIReg(rt)), \
+             unop(Iop_32to8, \
+                binop(Iop_And32, \
+                   mkNarrowTo32(ty, getIReg(rs)), \
+                   mkU32(0x0000001F) \
+                ) \
+             ) \
+          ), True \
+       ))
 
-static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
-{
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
-}
+#define SXX_PATTERN(op) \
+   putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
 
-static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
-{
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
-}
+#define ALU_PATTERN(op) \
+   putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
 
-static void putPC(IRExpr * e)
-{
-   stmt(IRStmt_Put(OFFB_PC, e));
-}
+#define ALUI_PATTERN(op) \
+   putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
 
-static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
-{
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   if (ty == Ity_I32)
-      return src;
-   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
-}
+#define ALUI_PATTERN64(op) \
+   putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
 
-/* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
-   of these combinations make sense. */
-static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
-{
-   IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
-   if (src_ty == dst_ty)
-      return e;
-   if (src_ty == Ity_I32 && dst_ty == Ity_I16)
-      return unop(Iop_32to16, e);
-   if (src_ty == Ity_I32 && dst_ty == Ity_I8)
-      return unop(Iop_32to8, e);
-   if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
-      vassert(mode64);
-      return unop(Iop_64to8, e);
-   }
-   if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
-      vassert(mode64);
-      return unop(Iop_64to16, e);
-   }
-   vpanic("narrowTo(mips)");
-   return 0;
-}
+#define ALU_PATTERN64(op) \
+   putIReg(rd, mkWidenFrom32(ty, binop(op, \
+                             mkNarrowTo32(ty, getIReg(rs)), \
+                             mkNarrowTo32(ty, getIReg(rt))), True));
 
-static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
-{
-   vassert(ty == Ity_F32 || ty == Ity_F64);
-   if (ty == Ity_F64) {
-      IRTemp t0, t1;
-      t0 = newTemp(Ity_I64);
-      t1 = newTemp(Ity_I32);
-      assign(t0, unop(Iop_ReinterpF64asI64, src));
-      assign(t1, unop(Iop_64to32, mkexpr(t0)));
-      return unop(Iop_ReinterpI32asF32, mkexpr(t1));
-   } else
-      return src;
-}
+#define FP_CONDITIONAL_CODE \
+   t3 = newTemp(Ity_I32);   \
+   assign(t3, binop(Iop_And32, \
+                 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
+                             binop(Iop_Shr32, getFCSR(), mkU8(23)), \
+                             binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
+                 mkU32(0x1)));
 
-static inline IRExpr *getHiFromF64(IRExpr * src)
-{
-   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
-   return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
-                                          unop(Iop_ReinterpF64asI64, src)));
-}
 
-static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
-{
-   vassert(ty == Ity_F32 || ty == Ity_F64);
-   if (ty == Ity_F64) {
-      IRTemp t0 = newTemp(Ity_I32);
-      IRTemp t1 = newTemp(Ity_I64);
-      assign(t0, unop(Iop_ReinterpF32asI32, src));
-      assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
-      return unop(Iop_ReinterpI64asF64, mkexpr(t1));
-   } else
-      return src;
-}
 
-/* Convenience function to move to next instruction on condition. */
-static void mips_next_insn_if(IRExpr *condition) {
-   vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
+#define ILLEGAL_INSTRUCTON \
+   putPC(mkU32(guest_PC_curr_instr + 4)); \
+   dres->jk_StopHere = Ijk_SigILL; \
+   dres->whatNext    = Dis_StopHere;
 
-   stmt(IRStmt_Exit(condition, Ijk_Boring,
-        mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
-                 IRConst_U32(guest_PC_curr_instr + 4),
-        OFFB_PC));
-}
+#define LLADDR_INVALID \
+   (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
 
-static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
+/*------------------------------------------------------------*/
+/*---                  Field helpers                       ---*/
+/*------------------------------------------------------------*/
+
+static Bool branch_or_jump(const UChar * addr)
 {
-   ULong branch_offset;
-   IRTemp t0;
+   UInt fmt;
+   UInt cins = getUInt(addr);
 
-   /* PC = PC + (SignExtend(signed_immed_24) << 2)
-      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
-      is added to the address of the instruction following
-      the branch (not the branch itself), in the branch delay slot, to form
-      a PC-relative effective target address. */
-   if (mode64)
-      branch_offset = extend_s_18to64(imm << 2);
-   else
-      branch_offset = extend_s_18to32(imm << 2);
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
+   UInt function = get_function(cins);
 
-   t0 = newTemp(Ity_I1);
-   assign(t0, guard);
+   /* bgtz, blez, bne, beq, jal */
+   if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
+       || opcode == 0x03 || opcode == 0x02) {
+      return True;
+   }
 
-   if (mode64)
-      stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                       IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
-   else
-      stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                       IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
+   /* bgez */
+   if (opcode == 0x01 && rt == 0x01) {
+      return True;
+   }
 
-   irsb->jumpkind = Ijk_Boring;
+   /* bgezal */
+   if (opcode == 0x01 && rt == 0x11) {
+      return True;
+   }
 
-   if (mode64)
-      return mkU64(guest_PC_curr_instr + 4 + branch_offset);
-   else
-      return mkU32(guest_PC_curr_instr + 4 + branch_offset);
-}
+   /* bltzal */
+   if (opcode == 0x01 && rt == 0x10) {
+      return True;
+   }
 
-static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
-{
-   ULong branch_offset;
-   IRTemp t0;
+   /* bltz */
+   if (opcode == 0x01 && rt == 0x00) {
+      return True;
+   }
 
-   if (link) {  /* LR (GPR31) = addr of the 2nd instr after branch instr */
-      if (mode64)
-         putIReg(31, mkU64(guest_PC_curr_instr + 8));
-      else
-         putIReg(31, mkU32(guest_PC_curr_instr + 8));
+   /* jalr */
+   if (opcode == 0x00 && function == 0x09) {
+      return True;
    }
 
-   /* PC = PC + (SignExtend(signed_immed_24) << 2)
-      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
-      is added to the address of the instruction following
-      the branch (not the branch itself), in the branch delay slot, to form
-      a PC-relative effective target address. */
+   /* jr */
+   if (opcode == 0x00 && function == 0x08) {
+      return True;
+   }
 
-   if (mode64)
-      branch_offset = extend_s_18to64(imm << 2);
-   else
-      branch_offset = extend_s_18to32(imm << 2);
+   if (opcode == 0x11) {
+      /* bc1f & bc1t */
+      fmt = get_fmt(cins);
 
-   t0 = newTemp(Ity_I1);
-   assign(t0, guard);
-   if (mode64)
-      *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
-                         IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
-                         OFFB_PC);
-   else
-      *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
-                         IRConst_U32(guest_PC_curr_instr + 4 +
-                                     (UInt) branch_offset), OFFB_PC);
-}
+      if (fmt == 0x08) {
+         return True;
+      }
 
-static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
-                               DisResult *dres)
-{
-   ULong branch_offset;
-   IRTemp t0;
+      /* MSA branches */
+      /* bnz.df, bz.df */
+      if (fmt >= 0x18) {
+         return True;
+      }
 
-   if (link) {  /* LR (GPR31) = addr of the instr after branch instr */
-      if (mode64)
-         putIReg(31, mkU64(guest_PC_curr_instr + 4));
-      else
-         putIReg(31, mkU32(guest_PC_curr_instr + 4));
-      dres->jk_StopHere = Ijk_Call;
-   } else {
-      dres->jk_StopHere = Ijk_Boring;
-   }
+      /* bnz.v */
+      if (fmt == 0x0f) {
+         return True;
+      }
 
-   dres->whatNext = Dis_StopHere;
+      /* bz.v */
+      if (fmt == 0x0b) {
+         return True;
+      }
 
-   /* PC = PC + (SignExtend(signed_immed_24) << 2)
-      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
-      is added to the address of the instruction following
-      the branch (not the branch itself), in the branch delay slot, to form
-      a PC-relative effective target address. */
+      /* R6 branches */
+      /* bc1eqz */
+      if (fmt == 0x09) {
+         return True;
+      }
 
-   if (mode64)
-      branch_offset = extend_s_18to64(imm << 2);
-   else
-      branch_offset = extend_s_18to32(imm << 2);
+      /* bc1nez */
+      if (fmt == 0x0D) {
+         return True;
+      }
+   }
 
-   t0 = newTemp(Ity_I1);
-   assign(t0, guard);
+   /* bposge32 */
+   if (opcode == 0x01 && rt == 0x1c) {
+      return True;
+   }
 
-   if (mode64) {
-      stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
-                         IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
-                         OFFB_PC));
-      putPC(mkU64(guest_PC_curr_instr + 4));
-   } else {
-      stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
-                         IRConst_U32(guest_PC_curr_instr + 4 +
-                                     (UInt) branch_offset), OFFB_PC));
-      putPC(mkU32(guest_PC_curr_instr + 4));
+   /* Cavium Specific instructions. */
+   if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
+      /* BBIT0, BBIT1, BBIT032, BBIT132 */
+      return True;
    }
-}
 
-static IRExpr *getFReg(UInt fregNo)
-{
-   vassert(fregNo < 32);
-   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
-   return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
+   return False;
 }
 
-static IRExpr *getDReg(UInt dregNo)
+static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
 {
-   vassert(dregNo < 32);
-   if (fp_mode64) {
-      return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
-   } else {
-      /* 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);
-      IRTemp t3 = newTemp(Ity_I32);
-      IRTemp t4 = newTemp(Ity_I32);
-      IRTemp t5 = newTemp(Ity_I64);
+   UInt cins = getUInt(addr);
 
-      assign(t0, getFReg(dregNo & (~1)));
-      assign(t1, getFReg(dregNo | 1));
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
+   UInt function = get_function(cins);
 
-      assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
-      assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
-      assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
-      assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
+   /* jal */
+   if (opcode == 0x02) {
+      return True;
+   }
 
-      return mkexpr(t2);
+   /* bgezal or bal(r6) */
+   if (opcode == 0x01 && rt == 0x11) {
+      return True;
+   }
+
+   /* bltzal */
+   if (opcode == 0x01 && rt == 0x10) {
+      return True;
+   }
+
+   /* jalr */
+   if (opcode == 0x00 && function == 0x09) {
+      return True;
    }
+
+   return False;
 }
 
-static void putFReg(UInt dregNo, IRExpr * e)
+static Bool branch_or_link_likely(const UChar * addr)
 {
-   vassert(dregNo < 32);
-   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
-   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+   UInt cins = getUInt(addr);
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
 
-   if (fp_mode64_fre) {
-      IRTemp t0 = newTemp(Ity_F32);
-      assign(t0, getLoFromF64(ty, e));
-#if defined (_MIPSEL)
-      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
-      if (dregNo & 1)
-         stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
-#else
-      stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
-      if (dregNo & 1)
-         stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
-#endif
-   } else {
-      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
-   }
+   /* bgtzl, blezl, bnel, beql */
+   if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
+      return True;
 
-   if (has_msa && fp_mode64) {
-      stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
-           binop(Iop_64HLtoV128,
-                    unop(Iop_ReinterpF64asI64, e),
-                    unop(Iop_ReinterpF64asI64, e))));
-   }
+   /* bgezl */
+   if (opcode == 0x01 && rt == 0x03)
+      return True;
+
+   /* bgezall */
+   if (opcode == 0x01 && rt == 0x13)
+      return True;
+
+   /* bltzall */
+   if (opcode == 0x01 && rt == 0x12)
+      return True;
+
+   /* bltzl */
+   if (opcode == 0x01 && rt == 0x02)
+      return True;
+
+   return False;
 }
 
-static void putDReg(UInt dregNo, IRExpr * e)
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments.    ---*/
+/*------------------------------------------------------------*/
+
+/* Generate an expression for SRC rotated right by ROT. */
+static IRExpr *genROR32(IRExpr * src, Int rot)
 {
-   if (fp_mode64) {
-      vassert(dregNo < 32);
-      IRType ty = Ity_F64;
-      vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
-      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
-      if (fp_mode64_fre) {
-         IRTemp t0 = newTemp(Ity_F32);
-         if (dregNo & 1) {
-            assign(t0, getLoFromF64(ty, e));
-#if defined (_MIPSEL)
-            stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
-#else
-            stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
-#endif
-         } else {
-            assign(t0, getHiFromF64(e));
-#if defined (_MIPSEL)
-            stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
-#else
-            stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
-#endif
-         }
-      }
-      if (has_msa)
-         stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
-              binop(Iop_64HLtoV128,
-                    unop(Iop_ReinterpF64asI64, e),
-                    unop(Iop_ReinterpF64asI64, e))));
-   } else {
-      vassert(dregNo < 32);
-      vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
-      IRTemp t1 = newTemp(Ity_F64);
-      IRTemp t4 = newTemp(Ity_I32);
-      IRTemp t5 = newTemp(Ity_I32);
-      IRTemp t6 = newTemp(Ity_I64);
-      assign(t1, e);
-      assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
-      assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  /* hi */
-      assign(t5, unop(Iop_64to32, mkexpr(t6)));    /* lo */
-      putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
-      putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
-   }
+   vassert(rot >= 0 && rot < 32);
+
+   if (rot == 0)
+      return src;
+
+   return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
+                binop(Iop_Shr32, src, mkU8(rot)));
 }
 
-static void setFPUCondCode(IRExpr * e, UInt cc)
+static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
 {
-   if (cc == 0) {
-      putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
-      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
+   IRTemp t0 = newTemp(Ity_I8);
+   IRTemp t1 = newTemp(Ity_I8);
+
+   assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
+   assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
+   return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
+                binop(Iop_Shr32, src, mkexpr(t0)));
+}
+
+static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
+{
+   vassert(dres->whatNext    == Dis_Continue);
+   vassert(dres->len         == 0);
+   vassert(dres->continueAt  == 0);
+   vassert(dres->jk_StopHere == Ijk_INVALID);
+   dres->whatNext    = Dis_StopHere;
+   dres->jk_StopHere = kind;
+   stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
+}
+
+static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
+{
+   vassert(dres->whatNext    == Dis_Continue);
+   vassert(dres->len         == 0);
+   vassert(dres->continueAt  == 0);
+   vassert(dres->jk_StopHere == Ijk_INVALID);
+   dres->whatNext    = Dis_StopHere;
+   dres->jk_StopHere = kind;
+   stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
+}
+
+/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
+   This function should be called before any other operation if widening
+   multiplications are used. */
+IRExpr *getAcc(UInt acNo)
+{
+   vassert(!mode64);
+   vassert(acNo <= 3);
+   return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
+}
+
+/* Get value from DSPControl register (helper function for MIPS32 DSP ASE
+   instructions). */
+IRExpr *getDSPControl(void)
+{
+   vassert(!mode64);
+   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
+}
+
+/* Fetch a byte from the guest insn stream. */
+static UChar getIByte(Int delta)
+{
+   return guest_code[delta];
+}
+
+IRExpr *getIReg(UInt iregNo)
+{
+   if (0 == iregNo) {
+      return mode64 ? mkU64(0x0) : mkU32(0x0);
    } else {
-      putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
-                               binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
-      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
+      IRType ty = mode64 ? Ity_I64 : Ity_I32;
+      vassert(iregNo < 32);
+      return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
    }
 }
 
-static IRExpr* get_IR_roundingmode ( void )
+static IRExpr *getWReg(UInt wregNo)
 {
-/*
-   rounding mode | MIPS | IR
-   ------------------------
-   to nearest    | 00  | 00
-   to zero       | 01  | 11
-   to +infinity  | 10  | 10
-   to -infinity  | 11  | 01
-*/
-   IRTemp rm_MIPS = newTemp(Ity_I32);
-   /* Last two bits in FCSR are rounding mode. */
+   vassert(wregNo <= 31);
+   return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
+}
 
+static IRExpr *getHI(void)
+{
    if (mode64)
-      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
-                                       guest_FCSR), Ity_I32), mkU32(3)));
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
    else
-      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
-                                       guest_FCSR), Ity_I32), mkU32(3)));
-
-   /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
+}
 
-   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
-                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+static IRExpr *getLO(void)
+{
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
 }
 
-static IRExpr* get_IR_roundingmode_MSA ( void ) {
-   /*
-      rounding mode | MIPS | IR
-      ------------------------
-      to nearest    | 00  | 00
-      to zero       | 01  | 11
-      to +infinity  | 10  | 10
-      to -infinity  | 11  | 01
-   */
-   IRTemp rm_MIPS = newTemp(Ity_I32);
-   /* Last two bits in MSACSR are rounding mode. */
+static IRExpr *getFCSR(void)
+{
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
+}
 
+static IRExpr *getLLaddr(void)
+{
    if (mode64)
-      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
-                            guest_MSACSR), Ity_I32), mkU32(3)));
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
    else
-      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
-                            guest_MSACSR), Ity_I32), mkU32(3)));
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
+}
 
-   /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
-   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
-                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+static IRExpr *getLLdata(void)
+{
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
 }
 
-/* sz, ULong -> IRExpr */
-static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
+static IRExpr *getMSACSR(void)
 {
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
 }
 
-static IRConst *mkSzConst ( IRType ty, ULong imm64 )
+/* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
+static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
 {
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
+   UInt pos = byte_pos * 8;
+
+   if (mode64)
+      return unop(Iop_64to8, binop(Iop_And64,
+                                   binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
+                                   mkU64(0xFF)));
+   else
+      return unop(Iop_32to8, binop(Iop_And32,
+                                   binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
+                                   mkU32(0xFF)));
 }
 
-/* Make sure we get valid 32 and 64bit addresses */
-static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
+static void putFCSR(IRExpr * e)
 {
-   vassert(ty == Ity_I32 || ty == Ity_I64);
-   return (ty == Ity_I64 ? (Addr64) addr :
-                           (Addr64) extend_s_32to64(toUInt(addr)));
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
 }
 
-/* Shift and Rotate instructions for MIPS64 */
-static Bool dis_instr_shrt ( UInt theInstr )
+static void putLLaddr(IRExpr * e)
 {
-   UInt opc2 = get_function(theInstr);
-   UChar regRs = get_rs(theInstr);
-   UChar regRt = get_rt(theInstr);
-   UChar regRd = get_rd(theInstr);
-   UChar uImmsa = get_sa(theInstr);
-   Long sImmsa = extend_s_16to64(uImmsa);
-   IRType ty = mode64 ? Ity_I64 : Ity_I32;
-   IRTemp tmp = newTemp(ty);
-   IRTemp tmpOr = newTemp(ty);
-   IRTemp tmpRt = newTemp(ty);
-   IRTemp tmpRs = newTemp(ty);
-   IRTemp tmpRd = newTemp(ty);
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
+}
 
-   assign(tmpRs, getIReg(regRs));
-   assign(tmpRt, getIReg(regRt));
+static void putLLdata(IRExpr * e)
+{
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
+}
 
-   switch (opc2) {
-      case 0x3A:
-         if ((regRs & 0x01) == 0) {
-            /* Doubleword Shift Right Logical - DSRL; MIPS64 */
-            DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
-            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
-            putIReg(regRd, mkexpr(tmpRd));
-         } else if ((regRs & 0x01) == 1) {
-            /* Doubleword Rotate Right - DROTR; MIPS64r2 */
-            vassert(mode64);
-            DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
-            IRTemp tmpL = newTemp(ty);
-            IRTemp tmpR = newTemp(ty);
-            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
-            assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
-            assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
-            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
-            putIReg(regRd, mkexpr(tmpRd));
-         } else
-            return False;
-         break;
+static void putMSACSR(IRExpr * e)
+{
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
+}
 
-      case 0x3E:
-         if ((regRs & 0x01) == 0) {
-            /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
-            DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
-            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
-            putIReg(regRd, mkexpr(tmpRd));
-         } else if ((regRs & 0x01) == 1) {
-            /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
-            DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
-            vassert(mode64);
-            IRTemp tmpL = newTemp(ty);
-            IRTemp tmpR = newTemp(ty);
-            /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
-            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
-            assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
-                              mkU8(63 - (uImmsa + 32))));
-            assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
-            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
-            putIReg(regRd, mkexpr(tmpRd));
-         } else
-            return False;
-         break;
+/* fs   - fpu source register number.
+   inst - fpu instruction that needs to be executed.
+   sz32 - size of source register.
+   opN  - number of operads:
+          1 - unary operation.
+          2 - binary operation. */
+static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
+{
+   IRDirty *d;
+   IRTemp fcsr = newTemp(Ity_I32);
 
-      case 0x16:
-         if ((uImmsa & 0x01) == 0) {
-            /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
-            DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
-            IRTemp tmpRs8 = newTemp(Ity_I8);
-            /* s = tmpRs[5..0] */
-            assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
-            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
-            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
-            putIReg(regRd, mkexpr(tmpRd));
-         } else if ((uImmsa & 0x01) == 1) {
-            /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
-            DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
-            IRTemp tmpL = newTemp(ty);
-            IRTemp tmpR = newTemp(ty);
-            IRTemp tmpRs8 = newTemp(Ity_I8);
-            IRTemp tmpLs8 = newTemp(Ity_I8);
-            IRTemp tmp64 = newTemp(ty);
-            /* s = tmpRs[5...0]
-               m = 64 - s
-               (tmpRt << s) | (tmpRt >> m) */
+   /* IRExpr_GSPTR() => 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_GSPTR(),
+                                          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_GSPTR(),
+                                          mkU32(fs),
+                                          mkU32(ft),
+                                          mkU32(inst)));
 
-            assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
-            assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
+   if (opN == 1) {  /* Unary operation. */
+      /* Declare we're reading guest state. */
+      if (sz32 || fp_mode64)
+         d->nFxState = 2;
+      else
+         d->nFxState = 3;
 
-            assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
-            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
+      vex_bzero(&d->fxState, sizeof(d->fxState));
 
-            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
-            assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
-            assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
-            assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
+      d->fxState[0].fx     = Ifx_Read;  /* read */
 
-            putIReg(regRd, mkexpr(tmpOr));
-         } else
-            return False;
-         break;
+      if (mode64)
+         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
+      else
+         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
 
-      case 0x38:  /* Doubleword Shift Left Logical - DSLL; MIPS64 */
-         DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
-         vassert(mode64);
-         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+      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);
 
-      case 0x3C:  /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
-         DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
-         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+      if (!(sz32 || fp_mode64)) {
+         d->fxState[2].fx     = Ifx_Read;  /* read */
+         d->fxState[2].offset = floatGuestRegOffset(fs + 1);
+         d->fxState[2].size   = sizeof(ULong);
+      }
+   } else if (opN == 2) {  /* Binary operation. */
+      /* Declare we're reading guest state. */
+      if (sz32 || fp_mode64)
+         d->nFxState = 3;
+      else
+         d->nFxState = 5;
 
-      case 0x14: {  /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
-         DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
-         IRTemp tmpRs8 = newTemp(Ity_I8);
+      vex_bzero(&d->fxState, sizeof(d->fxState));
 
-         assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
-         assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
-         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+      d->fxState[0].fx     = Ifx_Read;  /* read */
+
+      if (mode64)
+         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
+      else
+         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
+
+      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);
+      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(ULong);
+         d->fxState[4].fx     = Ifx_Read;  /* read */
+         d->fxState[4].offset = floatGuestRegOffset(ft + 1);
+         d->fxState[4].size   = sizeof(ULong);
       }
+   }
 
-      case 0x3B:  /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
-         DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
-         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+   stmt(IRStmt_Dirty(d));
 
-      case 0x3F:  /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
-                     MIPS64 */
-         DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
-         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+   putFCSR(mkexpr(fcsr));
+}
 
-      case 0x17: {  /* Doubleword Shift Right Arithmetic Variable - DSRAV;
-                       MIPS64 */
-         DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
-         IRTemp tmpRs8 = newTemp(Ity_I8);
-         assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
-         assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
-         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
-         putIReg(regRd, mkexpr(tmpRd));
-         break;
+/* ws, wt - source MSA register numbers.
+   inst   - MSA fp instruction that needs to be executed.
+   opN    - number of operads:
+             1 - unary operation.
+             2 - binary operation. */
+static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN)
+{
+   IRDirty *d;
+   IRTemp msacsr = newTemp(Ity_I32);
+   /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
+   d = unsafeIRDirty_1_N(msacsr, 0,
+                         "mips_dirtyhelper_calculate_MSACSR",
+                         &mips_dirtyhelper_calculate_MSACSR,
+                         mkIRExprVec_4(IRExpr_GSPTR(),
+                                       mkU32(ws),
+                                       mkU32(wt),
+                                       mkU32(inst)));
 
-      }
+   if (opN == 1) {  /* Unary operation. */
+      /* Declare we're reading guest state. */
+      d->nFxState = 2;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
+      d->fxState[0].fx     = Ifx_Read;  /* read */
 
-      default:
-         return False;
+      if (mode64)
+         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
+      else
+         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+
+      d->fxState[0].size   = sizeof(UInt);
+      d->fxState[1].fx     = Ifx_Read;  /* read */
+      d->fxState[1].offset = msaGuestRegOffset(ws);
+      d->fxState[1].size   = sizeof(ULong);
+   } else if (opN == 2) {  /* Binary operation. */
+      /* Declare we're reading guest state. */
+      d->nFxState = 3;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
+      d->fxState[0].fx     = Ifx_Read;  /* read */
+
+      if (mode64)
+         d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
+      else
+         d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
 
+      d->fxState[0].size   = sizeof(UInt);
+      d->fxState[1].fx     = Ifx_Read;  /* read */
+      d->fxState[1].offset = msaGuestRegOffset(ws);
+      d->fxState[1].size   = sizeof(ULong);
+      d->fxState[2].fx     = Ifx_Read;  /* read */
+      d->fxState[2].offset = msaGuestRegOffset(wt);
+      d->fxState[2].size   = sizeof(ULong);
    }
-   return True;
+
+   stmt(IRStmt_Dirty(d));
+   putMSACSR(mkexpr(msacsr));
 }
 
-static IROp mkSzOp ( IRType ty, IROp op8 )
+static IRExpr *getULR(void)
 {
-   Int adj;
-   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
-   vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
-           || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
-           || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
-           || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
-   adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
-   return adj + op8;
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
 }
 
-/*********************************************************/
-/*---             Floating Point Compare              ---*/
-/*********************************************************/
-/* Function that returns a string that represent mips cond
-   mnemonic for the input code. */
-static const HChar* showCondCode(UInt code) {
-   const HChar* ret;
-   switch (code) {
-      case 0: ret = "f"; break;
-      case 1: ret = "un"; break;
-      case 2: ret = "eq"; break;
-      case 3: ret = "ueq"; break;
-      case 4: ret = "olt"; break;
-      case 5: ret = "ult"; break;
-      case 6: ret = "ole"; break;
-      case 7: ret = "ule"; break;
-      case 8: ret = "sf"; break;
-      case 9: ret = "ngle"; break;
-      case 10: ret = "seq"; break;
-      case 11: ret = "ngl"; break;
-      case 12: ret = "lt"; break;
-      case 13: ret = "nge"; break;
-      case 14: ret = "le"; break;
-      case 15: ret = "ngt"; break;
-      default: vpanic("showCondCode"); break;
-   }
-   return ret;
+void putIReg(UInt archreg, IRExpr * e)
+{
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   vassert(archreg < 32);
+   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+
+   if (archreg != 0)
+      stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
 }
 
-static Bool dis_instr_CCondFmt ( UInt cins )
+static void putWReg(UInt wregNo, IRExpr * e)
 {
-   IRTemp t0, t1, t2, t3, tmp5, tmp6;
-   IRTemp ccIR = newTemp(Ity_I32);
-   IRTemp ccMIPS = newTemp(Ity_I32);
+   vassert(wregNo <= 31);
+   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
+   stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
+   stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
+                   unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
+}
+
+IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
+}
+
+void putLO(IRExpr * e)
+{
+   if (mode64) {
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
+   } else {
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
+      /* Add value to lower 32 bits of ac0 to maintain compatibility between
+         regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
+         unchanged. */
+      IRTemp t_lo = newTemp(Ity_I32);
+      IRTemp t_hi = newTemp(Ity_I32);
+      assign(t_lo, e);
+      assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
+      stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
+                      binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
+   }
+}
+
+void putHI(IRExpr * e)
+{
+   if (mode64) {
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
+   } else {
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
+      /* Add value to higher 32 bits of ac0 to maintain compatibility between
+         regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
+         unchanged. */
+      IRTemp t_lo = newTemp(Ity_I32);
+      IRTemp t_hi = newTemp(Ity_I32);
+      assign(t_hi, e);
+      assign(t_lo, unop(Iop_64to32, getAcc(0)));
+      stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
+                      binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
+   }
+}
+
+static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
+}
+
+static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
+}
+
+static void putPC(IRExpr * e)
+{
+   stmt(IRStmt_Put(OFFB_PC, e));
+}
+
+static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+
+   if (ty == Ity_I32)
+      return src;
+
+   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
+}
+
+/* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
+   of these combinations make sense. */
+static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
+{
+   IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
+
+   if (src_ty == dst_ty)
+      return e;
+
+   if (src_ty == Ity_I32 && dst_ty == Ity_I16)
+      return unop(Iop_32to16, e);
+
+   if (src_ty == Ity_I32 && dst_ty == Ity_I8)
+      return unop(Iop_32to8, e);
+
+   if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
+      vassert(mode64);
+      return unop(Iop_64to8, e);
+   }
+
+   if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
+      vassert(mode64);
+      return unop(Iop_64to16, e);
+   }
+
+   vpanic("narrowTo(mips)");
+   return 0;
+}
+
+static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_F32 || ty == Ity_F64);
+
+   if (ty == Ity_F64) {
+      IRTemp t0, t1;
+      t0 = newTemp(Ity_I64);
+      t1 = newTemp(Ity_I32);
+      assign(t0, unop(Iop_ReinterpF64asI64, src));
+      assign(t1, unop(Iop_64to32, mkexpr(t0)));
+      return unop(Iop_ReinterpI32asF32, mkexpr(t1));
+   } else
+      return src;
+}
+
+static inline IRExpr *getHiFromF64(IRExpr * src)
+{
+   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
+   return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
+                                          unop(Iop_ReinterpF64asI64, src)));
+}
+
+static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_F32 || ty == Ity_F64);
+
+   if (ty == Ity_F64) {
+      IRTemp t0 = newTemp(Ity_I32);
+      IRTemp t1 = newTemp(Ity_I64);
+      assign(t0, unop(Iop_ReinterpF32asI32, src));
+      assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
+      return unop(Iop_ReinterpI64asF64, mkexpr(t1));
+   } else
+      return src;
+}
+
+/* Convenience function to move to next instruction on condition. */
+static void mips_next_insn_if(IRExpr *condition)
+{
+   vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
+
+   stmt(IRStmt_Exit(condition, Ijk_Boring,
+                    mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+                    IRConst_U32(guest_PC_curr_instr + 4),
+                    OFFB_PC));
+}
+
+static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
+{
+   ULong branch_offset;
+   IRTemp t0;
+
+   /* PC = PC + (SignExtend(signed_immed_24) << 2)
+      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+      is added to the address of the instruction following
+      the branch (not the branch itself), in the branch delay slot, to form
+      a PC-relative effective target address. */
+   if (mode64)
+      branch_offset = extend_s_18to64(imm << 2);
+   else
+      branch_offset = extend_s_18to32(imm << 2);
+
+   t0 = newTemp(Ity_I1);
+   assign(t0, guard);
+
+   if (mode64)
+      stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                       IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
+   else
+      stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                       IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
+
+   irsb->jumpkind = Ijk_Boring;
+
+   if (mode64)
+      return mkU64(guest_PC_curr_instr + 4 + branch_offset);
+   else
+      return mkU32(guest_PC_curr_instr + 4 + branch_offset);
+}
+
+static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
+{
+   ULong branch_offset;
+   IRTemp t0;
+
+   if (link) {  /* LR (GPR31) = addr of the 2nd instr after branch instr */
+      if (mode64)
+         putIReg(31, mkU64(guest_PC_curr_instr + 8));
+      else
+         putIReg(31, mkU32(guest_PC_curr_instr + 8));
+   }
+
+   /* PC = PC + (SignExtend(signed_immed_24) << 2)
+      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+      is added to the address of the instruction following
+      the branch (not the branch itself), in the branch delay slot, to form
+      a PC-relative effective target address. */
+
+   if (mode64)
+      branch_offset = extend_s_18to64(imm << 2);
+   else
+      branch_offset = extend_s_18to32(imm << 2);
+
+   t0 = newTemp(Ity_I1);
+   assign(t0, guard);
+
+   if (mode64)
+      *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+                         IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+                         OFFB_PC);
+   else
+      *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+                         IRConst_U32(guest_PC_curr_instr + 4 +
+                                     (UInt) branch_offset), OFFB_PC);
+}
+
+static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
+                               DisResult *dres)
+{
+   ULong branch_offset;
+   IRTemp t0;
+
+   if (link) {  /* LR (GPR31) = addr of the instr after branch instr */
+      if (mode64)
+         putIReg(31, mkU64(guest_PC_curr_instr + 4));
+      else
+         putIReg(31, mkU32(guest_PC_curr_instr + 4));
+
+      dres->jk_StopHere = Ijk_Call;
+   } else {
+      dres->jk_StopHere = Ijk_Boring;
+   }
+
+   dres->whatNext = Dis_StopHere;
+
+   /* PC = PC + (SignExtend(signed_immed_24) << 2)
+      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+      is added to the address of the instruction following
+      the branch (not the branch itself), in the branch delay slot, to form
+      a PC-relative effective target address. */
+
+   if (mode64)
+      branch_offset = extend_s_18to64(imm << 2);
+   else
+      branch_offset = extend_s_18to32(imm << 2);
+
+   t0 = newTemp(Ity_I1);
+   assign(t0, guard);
+
+   if (mode64) {
+      stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+                       IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+                       OFFB_PC));
+      putPC(mkU64(guest_PC_curr_instr + 4));
+   } else {
+      stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+                       IRConst_U32(guest_PC_curr_instr + 4 +
+                                   (UInt) branch_offset), OFFB_PC));
+      putPC(mkU32(guest_PC_curr_instr + 4));
+   }
+}
+
+static IRExpr *getFReg(UInt fregNo)
+{
+   vassert(fregNo < 32);
+   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
+   return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
+}
+
+static IRExpr *getDReg(UInt dregNo)
+{
+   vassert(dregNo < 32);
+
+   if (fp_mode64) {
+      return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
+   } else {
+      /* 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);
+      IRTemp t3 = newTemp(Ity_I32);
+      IRTemp t4 = newTemp(Ity_I32);
+      IRTemp t5 = newTemp(Ity_I64);
+
+      assign(t0, getFReg(dregNo & (~1)));
+      assign(t1, getFReg(dregNo | 1));
+
+      assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
+      assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
+      assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
+      assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
+
+      return mkexpr(t2);
+   }
+}
+
+static void putFReg(UInt dregNo, IRExpr * e)
+{
+   vassert(dregNo < 32);
+   IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
+   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+
+   if (fp_mode64_fre) {
+      IRTemp t0 = newTemp(Ity_F32);
+      assign(t0, getLoFromF64(ty, e));
+#if defined (_MIPSEL)
+      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
+
+      if (dregNo & 1)
+         stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
+
+#else
+      stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
+
+      if (dregNo & 1)
+         stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
+
+#endif
+   } else {
+      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
+   }
+
+   if (has_msa && fp_mode64) {
+      stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
+                      binop(Iop_64HLtoV128,
+                            unop(Iop_ReinterpF64asI64, e),
+                            unop(Iop_ReinterpF64asI64, e))));
+   }
+}
+
+static void putDReg(UInt dregNo, IRExpr * e)
+{
+   if (fp_mode64) {
+      vassert(dregNo < 32);
+      IRType ty = Ity_F64;
+      vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+      stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
+
+      if (fp_mode64_fre) {
+         IRTemp t0 = newTemp(Ity_F32);
+
+         if (dregNo & 1) {
+            assign(t0, getLoFromF64(ty, e));
+#if defined (_MIPSEL)
+            stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
+#else
+            stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
+#endif
+         } else {
+            assign(t0, getHiFromF64(e));
+#if defined (_MIPSEL)
+            stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
+#else
+            stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
+#endif
+         }
+      }
+
+      if (has_msa)
+         stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
+                         binop(Iop_64HLtoV128,
+                               unop(Iop_ReinterpF64asI64, e),
+                               unop(Iop_ReinterpF64asI64, e))));
+   } else {
+      vassert(dregNo < 32);
+      vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
+      IRTemp t1 = newTemp(Ity_F64);
+      IRTemp t4 = newTemp(Ity_I32);
+      IRTemp t5 = newTemp(Ity_I32);
+      IRTemp t6 = newTemp(Ity_I64);
+      assign(t1, e);
+      assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
+      assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  /* hi */
+      assign(t5, unop(Iop_64to32, mkexpr(t6)));    /* lo */
+      putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
+      putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
+   }
+}
+
+static void setFPUCondCode(IRExpr * e, UInt cc)
+{
+   if (cc == 0) {
+      putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
+      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
+   } else {
+      putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
+                    binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
+      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
+   }
+}
+
+static IRExpr* get_IR_roundingmode ( void )
+{
+   /*
+      rounding mode | MIPS | IR
+      ------------------------
+      to nearest    | 00  | 00
+      to zero       | 01  | 11
+      to +infinity  | 10  | 10
+      to -infinity  | 11  | 01
+   */
+   IRTemp rm_MIPS = newTemp(Ity_I32);
+   /* Last two bits in FCSR are rounding mode. */
+
+   if (mode64)
+      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
+                            guest_FCSR), Ity_I32), mkU32(3)));
+   else
+      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
+                            guest_FCSR), Ity_I32), mkU32(3)));
+
+   /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+
+   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
+                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+}
+
+static IRExpr* get_IR_roundingmode_MSA ( void )
+{
+   /*
+      rounding mode | MIPS | IR
+      ------------------------
+      to nearest    | 00  | 00
+      to zero       | 01  | 11
+      to +infinity  | 10  | 10
+      to -infinity  | 11  | 01
+   */
+   IRTemp rm_MIPS = newTemp(Ity_I32);
+   /* Last two bits in MSACSR are rounding mode. */
+
+   if (mode64)
+      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
+                            guest_MSACSR), Ity_I32), mkU32(3)));
+   else
+      assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
+                            guest_MSACSR), Ity_I32), mkU32(3)));
+
+   /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
+                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+}
+
+/* sz, ULong -> IRExpr */
+static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
+}
+
+static IRConst *mkSzConst ( IRType ty, ULong imm64 )
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
+}
+
+/* Make sure we get valid 32 and 64bit addresses */
+static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return (ty == Ity_I64 ? (Addr64) addr :
+           (Addr64) extend_s_32to64(toUInt(addr)));
+}
+
+/* Shift and Rotate instructions for MIPS64 */
+static Bool dis_instr_shrt ( UInt theInstr )
+{
+   UInt opc2 = get_function(theInstr);
+   UChar regRs = get_rs(theInstr);
+   UChar regRt = get_rt(theInstr);
+   UChar regRd = get_rd(theInstr);
+   UChar uImmsa = get_sa(theInstr);
+   Long sImmsa = extend_s_16to64(uImmsa);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   IRTemp tmp = newTemp(ty);
+   IRTemp tmpOr = newTemp(ty);
+   IRTemp tmpRt = newTemp(ty);
+   IRTemp tmpRs = newTemp(ty);
+   IRTemp tmpRd = newTemp(ty);
+
+   assign(tmpRs, getIReg(regRs));
+   assign(tmpRt, getIReg(regRt));
+
+   switch (opc2) {
+      case 0x3A:
+         if ((regRs & 0x01) == 0) {
+            /* Doubleword Shift Right Logical - DSRL; MIPS64 */
+            DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
+            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
+            putIReg(regRd, mkexpr(tmpRd));
+         } else if ((regRs & 0x01) == 1) {
+            /* Doubleword Rotate Right - DROTR; MIPS64r2 */
+            vassert(mode64);
+            DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
+            IRTemp tmpL = newTemp(ty);
+            IRTemp tmpR = newTemp(ty);
+            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
+            assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
+            assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
+            putIReg(regRd, mkexpr(tmpRd));
+         } else
+            return False;
+
+         break;
+
+      case 0x3E:
+         if ((regRs & 0x01) == 0) {
+            /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
+            DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
+            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+            putIReg(regRd, mkexpr(tmpRd));
+         } else if ((regRs & 0x01) == 1) {
+            /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
+            DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+            vassert(mode64);
+            IRTemp tmpL = newTemp(ty);
+            IRTemp tmpR = newTemp(ty);
+            /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
+            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+            assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
+                              mkU8(63 - (uImmsa + 32))));
+            assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
+            putIReg(regRd, mkexpr(tmpRd));
+         } else
+            return False;
+
+         break;
+
+      case 0x16:
+         if ((uImmsa & 0x01) == 0) {
+            /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
+            DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
+            IRTemp tmpRs8 = newTemp(Ity_I8);
+            /* s = tmpRs[5..0] */
+            assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
+            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+            assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+            putIReg(regRd, mkexpr(tmpRd));
+         } else if ((uImmsa & 0x01) == 1) {
+            /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
+            DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
+            IRTemp tmpL = newTemp(ty);
+            IRTemp tmpR = newTemp(ty);
+            IRTemp tmpRs8 = newTemp(Ity_I8);
+            IRTemp tmpLs8 = newTemp(Ity_I8);
+            IRTemp tmp64 = newTemp(ty);
+            /* s = tmpRs[5...0]
+               m = 64 - s
+               (tmpRt << s) | (tmpRt >> m) */
+
+            assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+            assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
+
+            assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
+            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
+
+            assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+            assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
+            assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
+            assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
+
+            putIReg(regRd, mkexpr(tmpOr));
+         } else
+            return False;
+
+         break;
+
+      case 0x38:  /* Doubleword Shift Left Logical - DSLL; MIPS64 */
+         DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
+         vassert(mode64);
+         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+
+      case 0x3C:  /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
+         DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+
+      case 0x14: {  /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
+         DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
+         IRTemp tmpRs8 = newTemp(Ity_I8);
+
+         assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+         assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+         assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+      }
+
+      case 0x3B:  /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
+         DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
+         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+
+      case 0x3F:  /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
+                     MIPS64 */
+         DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+
+      case 0x17: {
+         /* Doubleword Shift Right Arithmetic Variable - DSRAV;
+                          MIPS64 */
+         DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
+         IRTemp tmpRs8 = newTemp(Ity_I8);
+         assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+         assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+         assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+         putIReg(regRd, mkexpr(tmpRd));
+         break;
+
+      }
+
+      default:
+         return False;
+
+   }
+
+   return True;
+}
+
+static IROp mkSzOp ( IRType ty, IROp op8 )
+{
+   Int adj;
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
+   vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
+           || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
+           || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
+           || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
+   adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
+   return adj + op8;
+}
+
+/*********************************************************/
+/*---             Floating Point Compare              ---*/
+/*********************************************************/
+/* Function that returns a string that represent mips cond
+   mnemonic for the input code. */
+static const HChar* showCondCode(UInt code)
+{
+   const HChar* ret;
+
+   switch (code) {
+      case 0:
+         ret = "f";
+         break;
+
+      case 1:
+         ret = "un";
+         break;
+
+      case 2:
+         ret = "eq";
+         break;
+
+      case 3:
+         ret = "ueq";
+         break;
+
+      case 4:
+         ret = "olt";
+         break;
+
+      case 5:
+         ret = "ult";
+         break;
+
+      case 6:
+         ret = "ole";
+         break;
+
+      case 7:
+         ret = "ule";
+         break;
+
+      case 8:
+         ret = "sf";
+         break;
+
+      case 9:
+         ret = "ngle";
+         break;
+
+      case 10:
+         ret = "seq";
+         break;
+
+      case 11:
+         ret = "ngl";
+         break;
+
+      case 12:
+         ret = "lt";
+         break;
+
+      case 13:
+         ret = "nge";
+         break;
+
+      case 14:
+         ret = "le";
+         break;
+
+      case 15:
+         ret = "ngt";
+         break;
+
+      default:
+         vpanic("showCondCode");
+         break;
+   }
+
+   return ret;
+}
+
+static Bool dis_instr_CCondFmt ( UInt cins )
+{
+   IRTemp t0, t1, t2, t3, tmp5, tmp6;
+   IRTemp ccIR = newTemp(Ity_I32);
+   IRTemp ccMIPS = newTemp(Ity_I32);
    UInt FC = get_FC(cins);
    UInt fmt = get_fmt(cins);
    UInt fs = get_fs(cins);
    UInt ft = get_ft(cins);
    UInt cond = get_cond(cins);
 
-   if (FC == 0x3) {  /* C.cond.fmt */
-      UInt fpc_cc = get_fpc_cc(cins);
-      switch (fmt) {
-         case 0x10: {  /* C.cond.S */
-            DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
-            if (fp_mode64) {
-               t0 = newTemp(Ity_I32);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I32);
+   if (FC == 0x3) {  /* C.cond.fmt */
+      UInt fpc_cc = get_fpc_cc(cins);
+
+      switch (fmt) {
+         case 0x10: {  /* C.cond.S */
+            DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
+
+            if (fp_mode64) {
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+
+               tmp5 = newTemp(Ity_F64);
+               tmp6 = newTemp(Ity_F64);
+
+               assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
+                                 getFReg(fs))));
+               assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
+                                 getFReg(ft))));
+
+               assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
+               putHI(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
+                                   mkexpr(ccIR), True));
+               /* Map compare result from IR to MIPS
+                  FP cmp result | MIPS | IR
+                  --------------------------
+                  UN            | 0x1 | 0x45
+                  EQ            | 0x2 | 0x40
+                  GT            | 0x4 | 0x00
+                  LT            | 0x8 | 0x01
+                */
+
+               /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+               assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+                                    binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+                                          binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+                                          binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+                                                binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+                                                mkU32(1))))));
+               putLO(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
+                                   mkexpr(ccMIPS), True));
+
+               /* UN */
+               assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+               /* EQ */
+               assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                                 mkU8(0x1)), mkU32(0x1)));
+               /* NGT */
+               assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+                                                mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+               /* LT */
+               assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                                 mkU8(0x3)), mkU32(0x1)));
+
+               switch (cond) {
+                  case 0x0:
+                     setFPUCondCode(mkU32(0), fpc_cc);
+                     break;
+
+                  case 0x1:
+                     setFPUCondCode(mkexpr(t0), fpc_cc);
+                     break;
+
+                  case 0x2:
+                     setFPUCondCode(mkexpr(t1), fpc_cc);
+                     break;
+
+                  case 0x3:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x4:
+                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                     break;
+
+                  case 0x5:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x6:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x7:
+                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                     break;
+
+                  case 0x8:
+                     setFPUCondCode(mkU32(0), fpc_cc);
+                     break;
+
+                  case 0x9:
+                     setFPUCondCode(mkexpr(t0), fpc_cc);
+                     break;
+
+                  case 0xA:
+                     setFPUCondCode(mkexpr(t1), fpc_cc);
+                     break;
+
+                  case 0xB:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xC:
+                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                     break;
+
+                  case 0xD:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xE:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xF:
+                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                     break;
+
+                  default:
+                     return False;
+               }
+
+            } else {
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+
+               assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
+                                  unop(Iop_F32toF64, getFReg(ft))));
+               /* Map compare result from IR to MIPS
+                  FP cmp result | MIPS | IR
+                  --------------------------
+                  UN            | 0x1 | 0x45
+                  EQ            | 0x2 | 0x40
+                  GT            | 0x4 | 0x00
+                  LT            | 0x8 | 0x01
+                */
+
+               /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+               assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+                                    binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+                                          binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
+                                          mkU32(2)), binop(Iop_And32,
+                                                binop(Iop_Xor32, mkexpr(ccIR),
+                                                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+                                                mkU32(1))))));
+               /* UN */
+               assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+               /* EQ */
+               assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                                 mkU8(0x1)), mkU32(0x1)));
+               /* NGT */
+               assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+                                                mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+               /* LT */
+               assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                                 mkU8(0x3)), mkU32(0x1)));
+
+               switch (cond) {
+                  case 0x0:
+                     setFPUCondCode(mkU32(0), fpc_cc);
+                     break;
+
+                  case 0x1:
+                     setFPUCondCode(mkexpr(t0), fpc_cc);
+                     break;
+
+                  case 0x2:
+                     setFPUCondCode(mkexpr(t1), fpc_cc);
+                     break;
+
+                  case 0x3:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x4:
+                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                     break;
+
+                  case 0x5:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x6:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0x7:
+                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                     break;
+
+                  case 0x8:
+                     setFPUCondCode(mkU32(0), fpc_cc);
+                     break;
+
+                  case 0x9:
+                     setFPUCondCode(mkexpr(t0), fpc_cc);
+                     break;
+
+                  case 0xA:
+                     setFPUCondCode(mkexpr(t1), fpc_cc);
+                     break;
+
+                  case 0xB:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xC:
+                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                     break;
+
+                  case 0xD:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xE:
+                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                    fpc_cc);
+                     break;
+
+                  case 0xF:
+                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                     break;
+
+                  default:
+                     return False;
+               }
+            }
+         }
+         break;
+
+         case 0x11: {  /* C.cond.D */
+            DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I32);
+            assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+            /* Map compare result from IR to MIPS
+               FP cmp result | MIPS | IR
+               --------------------------
+               UN            | 0x1 | 0x45
+               EQ            | 0x2 | 0x40
+               GT            | 0x4 | 0x00
+               LT            | 0x8 | 0x01
+             */
+
+            /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+                                 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+                                       binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+                                       binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+                                             binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+                                             mkU32(1))))));
+
+            /* UN */
+            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+            /* EQ */
+            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                              mkU8(0x1)), mkU32(0x1)));
+            /* NGT */
+            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+                                             mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+            /* LT */
+            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                                              mkU8(0x3)), mkU32(0x1)));
+
+            switch (cond) {
+               case 0x0:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+
+               case 0x1:
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+
+               case 0x2:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+
+               case 0x3:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                 fpc_cc);
+                  break;
+
+               case 0x4:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+
+               case 0x5:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                 fpc_cc);
+                  break;
+
+               case 0x6:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                 fpc_cc);
+                  break;
+
+               case 0x7:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+
+               case 0x8:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+
+               case 0x9:
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+
+               case 0xA:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+
+               case 0xB:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                 fpc_cc);
+                  break;
+
+               case 0xC:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+
+               case 0xD:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                 fpc_cc);
+                  break;
+
+               case 0xE:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                 fpc_cc);
+                  break;
+
+               case 0xF:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+
+               default:
+                  return False;
+            }
+         }
+         break;
+
+         default:
+            return False;
+      }
+   } else {
+      return False;
+   }
+
+   return True;
+}
+
+/*********************************************************/
+/*---        Branch Instructions for mips64           ---*/
+/*********************************************************/
+static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
+                               Bool(*resteerOkFn) (void *, Addr),
+                               void *callback_opaque, IRStmt ** set )
+{
+   UInt jmpKind = 0;
+   UChar opc1 = get_opcode(theInstr);
+   UChar regRs = get_rs(theInstr);
+   UChar regRt = get_rt(theInstr);
+   UInt offset = get_imm(theInstr);
+   Long sOffset = extend_s_16to64(offset);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
+
+   IRTemp tmp = newTemp(ty);
+   IRTemp tmpRs = newTemp(ty);
+   IRTemp tmpRt = newTemp(ty);
+   IRTemp tmpLt = newTemp(ty);
+   IRTemp tmpReg0 = newTemp(ty);
+
+   UChar regLnk = 31;   /* reg 31 is link reg in MIPS */
+   Addr64 addrTgt = 0;
+   Addr64 cia = guest_PC_curr_instr;
+
+   IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
+   IRExpr *eNia = mkSzImm(ty, cia + 8);
+   IRExpr *eCond = NULL;
+
+   assign(tmpRs, getIReg(regRs));
+   assign(tmpRt, getIReg(regRt));
+   assign(tmpReg0, getIReg(0));
+
+   eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
+
+   switch (opc1) {
+      case 0x01:
+         switch (regRt) {
+            case 0x00: {  /* BLTZ rs, offset */
+               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+               IRTemp tmpLtRes = newTemp(Ity_I1);
+
+               assign(tmp, eConst0);
+               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+
+               eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
+                             mkexpr(tmpReg0));
+
+               jmpKind = Ijk_Boring;
+               break;
+            }
+
+            case 0x01: {  /* BGEZ rs, offset */
+               IRTemp tmpLtRes = newTemp(Ity_I1);
+               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+
+               assign(tmp, eConst0);
+               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+               eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
+                             mkexpr(tmpReg0));
+
+               jmpKind = Ijk_Boring;
+               break;
+            }
+
+            case 0x11: {  /* BGEZAL rs, offset */
+               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+               putIReg(regLnk, eNia);
+               IRTemp tmpLtRes = newTemp(Ity_I1);
+
+               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
+               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+
+               eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
+                             mkexpr(tmpReg0));
+
+               jmpKind = Ijk_Call;
+               break;
+            }
+
+            case 0x10: {  /* BLTZAL rs, offset */
+               IRTemp tmpLtRes = newTemp(Ity_I1);
+               IRTemp tmpRes = newTemp(ty);
+
+               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+               putIReg(regLnk, eNia);
+
+               assign(tmp, eConst0);
+               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+               assign(tmpRes, mode64 ? unop(Iop_1Uto64,
+                                            mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+               eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
+                             mkexpr(tmpReg0));
+
+               jmpKind = Ijk_Call;
+               break;
+            }
+
+         }
+
+         break;
+
+      default:
+         return False;
+   }
+
+   *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
+   return True;
+}
+
+/*********************************************************/
+/*---         Cavium Specific Instructions            ---*/
+/*********************************************************/
+
+/* Convenience function to yield to thread scheduler */
+static void jump_back(IRExpr *condition)
+{
+   stmt( IRStmt_Exit(condition,
+                     Ijk_Yield,
+                     IRConst_U64( guest_PC_curr_instr ),
+                     OFFB_PC) );
+}
+
+/* Based on s390_irgen_load_and_add32. */
+static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
+                              IRTemp expd, UChar rd, Bool putIntoRd)
+{
+   IRCAS *cas;
+   IRTemp old_mem = newTemp(Ity_I32);
+   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
+
+   cas = mkIRCAS(IRTemp_INVALID, old_mem,
+#if defined (_MIPSEL)
+                 Iend_LE, mkexpr(op1addr),
+#else /* _MIPSEB */
+                 Iend_BE, mkexpr(op1addr),
+#endif
+                 NULL, mkexpr(expd), /* expected value */
+                 NULL, mkexpr(new_val)  /* new value */);
+   stmt(IRStmt_CAS(cas));
+
+   /* If old_mem contains the expected value, then the CAS succeeded.
+      Otherwise, it did not */
+   jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
+
+   if (putIntoRd)
+      putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
+}
+
+/* Based on s390_irgen_load_and_add64. */
+static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
+                              IRTemp expd, UChar rd, Bool putIntoRd)
+{
+   IRCAS *cas;
+   IRTemp old_mem = newTemp(Ity_I64);
+   vassert(mode64);
+   cas = mkIRCAS(IRTemp_INVALID, old_mem,
+#if defined (_MIPSEL)
+                 Iend_LE, mkexpr(op1addr),
+#else /* _MIPSEB */
+                 Iend_BE, mkexpr(op1addr),
+#endif
+                 NULL, mkexpr(expd), /* expected value */
+                 NULL, mkexpr(new_val)  /* new value */);
+   stmt(IRStmt_CAS(cas));
+
+   /* If old_mem contains the expected value, then the CAS succeeded.
+      Otherwise, it did not */
+   jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
 
-               tmp5 = newTemp(Ity_F64);
-               tmp6 = newTemp(Ity_F64);
+   if (putIntoRd)
+      putIReg(rd, mkexpr(old_mem));
+}
 
-               assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
-                                 getFReg(fs))));
-               assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
-                                 getFReg(ft))));
+static Bool dis_instr_CVM ( UInt theInstr )
+{
+   UChar  opc2     = get_function(theInstr);
+   UChar  opc1     = get_opcode(theInstr);
+   UChar  regRs    = get_rs(theInstr);
+   UChar  regRt    = get_rt(theInstr);
+   UChar  regRd    = get_rd(theInstr);
+   /* MIPS trap instructions extract code from theInstr[15:6].
+      Cavium OCTEON instructions SNEI, SEQI extract immediate operands
+      from the same bit field [15:6]. */
+   UInt   imm      = get_code(theInstr);
+   UChar  lenM1    = get_msb(theInstr);
+   UChar  p        = get_lsb(theInstr);
+   IRType ty       = mode64 ? Ity_I64 : Ity_I32;
+   IRTemp tmp      = newTemp(ty);
+   IRTemp tmpRs    = newTemp(ty);
+   IRTemp tmpRt    = newTemp(ty);
+   IRTemp t1       = newTemp(ty);
+   UInt size;
+   assign(tmpRs, getIReg(regRs));
 
-               assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
-               putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
-                                   mkexpr(ccIR), True));
-               /* Map compare result from IR to MIPS
-                  FP cmp result | MIPS | IR
-                  --------------------------
-                  UN            | 0x1 | 0x45
-                  EQ            | 0x2 | 0x40
-                  GT            | 0x4 | 0x00
-                  LT            | 0x8 | 0x01
-                */
+   switch (opc1) {
+      case 0x1C: {
+         switch (opc2) {
+            case 0x03: {  /* DMUL rd, rs, rt */
+               DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
+               IRTemp t0 = newTemp(Ity_I128);
+               assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
+               putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
+               break;
+            }
 
-               /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
-               assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
-                              binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
-                              binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)),
-                              binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
-                              binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
-                              mkU32(1))))));
-               putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
-                                   mkexpr(ccMIPS), True));
+            case 0x18: {  /* Store Atomic Add Word - SAA; Cavium OCTEON */
+               DIP("saa r%u, (r%u)", regRt, regRs);
+               IRTemp addr = newTemp(Ity_I64);
+               IRTemp new_val = newTemp(Ity_I32);
+               IRTemp old = newTemp(Ity_I32);
+               assign(addr, getIReg(regRs));
+               assign(old, load(Ity_I32, mkexpr(addr)));
+               assign(new_val, binop(Iop_Add32,
+                                     mkexpr(old),
+                                     mkNarrowTo32(ty, getIReg(regRt))));
+               mips_load_store32(addr, new_val, old, 0, False);
+               break;
+            }
 
-               /* UN */
-               assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
-               /* EQ */
-               assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                                                 mkU8(0x1)), mkU32(0x1)));
-               /* NGT */
-               assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
-                                 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1)));
-               /* LT */
-               assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                                                 mkU8(0x3)), mkU32(0x1)));
-               switch (cond) {
-                  case 0x0:
-                     setFPUCondCode(mkU32(0), fpc_cc);
-                     break;
-                  case 0x1:
-                     setFPUCondCode(mkexpr(t0), fpc_cc);
-                     break;
-                  case 0x2:
-                     setFPUCondCode(mkexpr(t1), fpc_cc);
-                     break;
-                  case 0x3:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                          fpc_cc);
-                     break;
-                  case 0x4:
-                     setFPUCondCode(mkexpr(t3), fpc_cc);
+            /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
+            case 0x19: {
+               DIP( "saad r%u, (r%u)", regRt, regRs);
+               IRTemp addr = newTemp(Ity_I64);
+               IRTemp new_val = newTemp(Ity_I64);
+               IRTemp old = newTemp(Ity_I64);
+               assign(addr, getIReg(regRs));
+               assign(old, load(Ity_I64, mkexpr(addr)));
+               assign(new_val, binop(Iop_Add64,
+                                     mkexpr(old),
+                                     getIReg(regRt)));
+               mips_load_store64(addr, new_val, old, 0, False);
+               break;
+            }
+
+            /* LAI, LAID, LAD, LADD, LAS, LASD,
+               LAC, LACD, LAA, LAAD, LAW, LAWD */
+            case 0x1f: {
+               UInt opc3 = get_sa(theInstr);
+               IRTemp addr = newTemp(Ity_I64);
+
+               switch (opc3) {
+                  /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
+                  case 0x02: {
+                     DIP("lai r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Add32,
+                                           mkexpr(old),
+                                           mkU32(1)));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0x5:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                          fpc_cc);
+                  }
+
+                  /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
+                  case 0x03: {
+                     DIP("laid r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Add64,
+                                           mkexpr(old),
+                                           mkU64(1)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
-                  case 0x6:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                          fpc_cc);
+                  }
+
+                  /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
+                  case 0x06: {
+                     DIP("lad r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Sub32,
+                                           mkexpr(old),
+                                           mkU32(1)));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0x7:
-                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                  }
+
+                  /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
+                  case 0x07: {
+                     DIP("ladd r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Sub64,
+                                           mkexpr(old),
+                                           mkU64(1)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
-                  case 0x8:
-                     setFPUCondCode(mkU32(0), fpc_cc);
+                  }
+
+                  /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
+                  case 0x0a: {
+                     DIP("las r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, mkU32(0xffffffff));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0x9:
-                     setFPUCondCode(mkexpr(t0), fpc_cc);
+                  }
+
+                  /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
+                  case 0x0b: {
+                     DIP("lasd r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, mkU64(0xffffffffffffffffULL));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
-                  case 0xA:
-                     setFPUCondCode(mkexpr(t1), fpc_cc);
+                  }
+
+                  /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
+                  case 0x0e: {
+                     DIP("lac r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, mkU32(0));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0xB:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                          fpc_cc);
+                  }
+
+                  /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
+                  case 0x0f: {
+                     DIP("lacd r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, mkU64(0));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
-                  case 0xC:
-                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                  }
+
+                  /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
+                  case 0x12: {
+                     DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Add32,
+                                           mkexpr(old),
+                                           mkNarrowTo32(ty, getIReg(regRt))));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0xD:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                          fpc_cc);
+                  }
+
+                  /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
+                  case 0x13: {
+                     DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     assign(new_val, binop(Iop_Add64,
+                                           load(Ity_I64, mkexpr(addr)),
+                                           getIReg(regRt)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
-                  case 0xE:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                          fpc_cc);
+                  }
+
+                  /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
+                  case 0x16: {
+                     DIP("law r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I32);
+                     IRTemp old = newTemp(Ity_I32);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
+                     assign(old, load(Ity_I32, mkexpr(addr)));
+                     mips_load_store32(addr, new_val, old, regRd, True);
                      break;
-                  case 0xF:
-                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                  }
+
+                  /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
+                  case 0x17: {
+                     DIP("lawd r%u,(r%u)\n", regRd, regRs);
+                     IRTemp new_val = newTemp(Ity_I64);
+                     IRTemp old = newTemp(Ity_I64);
+                     assign(addr, getIReg(regRs));
+                     assign(new_val, getIReg(regRt));
+                     assign(old, load(Ity_I64, mkexpr(addr)));
+                     mips_load_store64(addr, new_val, old, regRd, True);
                      break;
+                  }
 
                   default:
+                     vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
+                     vex_printf("Instruction=0x%08x\n", theInstr);
                      return False;
                }
 
-            } else {
-               t0 = newTemp(Ity_I32);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I32);
+               break;
+            }
+
+            /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
+            case 0x28: {
+               DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
+               IRTemp t0 = newTemp(Ity_I8);
+
+               assign(t0, binop(Iop_Add8,
+                                mkNarrowTo8(ty, getIReg(regRs)),
+                                mkNarrowTo8(ty, getIReg(regRt))));
+
+               if (mode64)
+                  putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
+                                       unop(Iop_8Uto64, mkexpr(t0)),
+                                       mkSzImm(ty, 0xFF)));
+               else
+                  putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
+                                       unop(Iop_8Uto32, mkexpr(t0)),
+                                       mkSzImm(ty, 0xFF)));
+
+               break;
+            }
+
+            case 0x2c: {  /* Count Ones in a Word - POP; Cavium OCTEON */
+               int i, shift[5];
+               IRTemp mask[5];
+               IRTemp old = newTemp(ty);
+               IRTemp nyu = IRTemp_INVALID;
+               assign(old, getIReg(regRs));
+               DIP("pop r%u, r%u", regRd, regRs);
+
+               for (i = 0; i < 5; i++) {
+                  mask[i] = newTemp(ty);
+                  shift[i] = 1 << i;
+               }
+
+               if (mode64) {
+                  assign(mask[0], mkU64(0x0000000055555555));
+                  assign(mask[1], mkU64(0x0000000033333333));
+                  assign(mask[2], mkU64(0x000000000F0F0F0F));
+                  assign(mask[3], mkU64(0x0000000000FF00FF));
+                  assign(mask[4], mkU64(0x000000000000FFFF));
+
+                  for (i = 0; i < 5; i++) {
+                     nyu = newTemp(ty);
+                     assign(nyu,
+                            binop(Iop_Add64,
+                                  binop(Iop_And64,
+                                        mkexpr(old), mkexpr(mask[i])),
+                                  binop(Iop_And64,
+                                        binop(Iop_Shr64,
+                                              mkexpr(old), mkU8(shift[i])),
+                                        mkexpr(mask[i]))));
+                     old = nyu;
+                  }
+               } else {
+                  assign(mask[0], mkU32(0x55555555));
+                  assign(mask[1], mkU32(0x33333333));
+                  assign(mask[2], mkU32(0x0F0F0F0F));
+                  assign(mask[3], mkU32(0x00FF00FF));
+                  assign(mask[4], mkU32(0x0000FFFF));
+                  assign(old, getIReg(regRs));
+
+                  for (i = 0; i < 5; i++) {
+                     nyu = newTemp(ty);
+                     assign(nyu,
+                            binop(Iop_Add32,
+                                  binop(Iop_And32,
+                                        mkexpr(old), mkexpr(mask[i])),
+                                  binop(Iop_And32,
+                                        binop(Iop_Shr32,
+                                              mkexpr(old), mkU8(shift[i])),
+                                        mkexpr(mask[i]))));
+                     old = nyu;
+                  }
+               }
+
+               putIReg(regRd, mkexpr(nyu));
+               break;
+            }
+
+            /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
+            case 0x2d: {
+               int i, shift[6];
+               IRTemp mask[6];
+               IRTemp old = newTemp(ty);
+               IRTemp nyu = IRTemp_INVALID;
+               DIP("dpop r%u, r%u", regRd, regRs);
+
+               for (i = 0; i < 6; i++) {
+                  mask[i] = newTemp(ty);
+                  shift[i] = 1 << i;
+               }
+
+               vassert(mode64); /*Caution! Only for Mode 64*/
+               assign(mask[0], mkU64(0x5555555555555555ULL));
+               assign(mask[1], mkU64(0x3333333333333333ULL));
+               assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
+               assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
+               assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
+               assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
+               assign(old, getIReg(regRs));
+
+               for (i = 0; i < 6; i++) {
+                  nyu = newTemp(Ity_I64);
+                  assign(nyu,
+                         binop(Iop_Add64,
+                               binop(Iop_And64,
+                                     mkexpr(old), mkexpr(mask[i])),
+                               binop(Iop_And64,
+                                     binop(Iop_Shr64,
+                                           mkexpr(old), mkU8(shift[i])),
+                                     mkexpr(mask[i]))));
+                  old = nyu;
+               }
+
+               putIReg(regRd, mkexpr(nyu));
+               break;
+            }
+
+            case 0x32:  /* 5. CINS rd, rs, p, lenm1 */
+               DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1);
+               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
+                                     mkU8(64 - ( lenM1 + 1 ))));
+               assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
+                                     mkU8(64 - (p + lenM1 + 1))));
+               putIReg( regRt, mkexpr(tmpRt));
+               break;
+
+            case 0x33:  /* 6. CINS32 rd, rs, p+32, lenm1 */
+               DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p + 32, lenM1);
+               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
+                                     mkU8(64 - ( lenM1 + 1 ))));
+               assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
+                                     mkU8(32 - (p + lenM1 + 1))));
+               putIReg( regRt, mkexpr(tmpRt));
+               break;
+
+            case 0x3A:  /* 3. EXTS rt, rs, p len */
+               DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
+               size = lenM1 + 1;  /* lenm1+1 */
+               UChar lsAmt = 64 - (p + size);  /* p+lenm1+1 */
+               UChar rsAmt = 64 - size;  /* lenm1+1 */
+               tmp = newTemp(Ity_I64);
+               assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+               putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
+               break;
+
+            case 0x3B:  /* 4. EXTS32 rt, rs, p len */
+               DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
+               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
+                                     mkU8(32 - (p + lenM1 + 1))));
+               assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
+                                     mkU8(64 - (lenM1 + 1))) );
+               putIReg( regRt, mkexpr(tmpRt));
+               break;
+
+            case 0x2B:  /* 20. SNE rd, rs, rt */
+               DIP("sne r%u, r%u, r%u", regRd, regRs, regRt);
+
+               if (mode64)
+                  putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
+                                                        getIReg(regRs),
+                                                        getIReg(regRt))));
+               else
+                  putIReg(regRd, unop(Iop_1Uto32, binop(Iop_CmpNE32,
+                                                        getIReg(regRs),
+                                                        getIReg(regRt))));
+
+               break;
+
+            case 0x2A:  /* Set Equals - SEQ; Cavium OCTEON */
+               DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
+
+               if (mode64)
+                  putIReg(regRd, unop(Iop_1Uto64,
+                                      binop(Iop_CmpEQ64, getIReg(regRs),
+                                            getIReg(regRt))));
+               else
+                  putIReg(regRd, unop(Iop_1Uto32,
+                                      binop(Iop_CmpEQ32, getIReg(regRs),
+                                            getIReg(regRt))));
+
+               break;
+
+            case 0x2E:  /* Set Equals Immediate - SEQI; Cavium OCTEON */
+               DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
+
+               if (mode64)
+                  putIReg(regRt, unop(Iop_1Uto64,
+                                      binop(Iop_CmpEQ64, getIReg(regRs),
+                                            mkU64(extend_s_10to64(imm)))));
+               else
+                  putIReg(regRt, unop(Iop_1Uto32,
+                                      binop(Iop_CmpEQ32, getIReg(regRs),
+                                            mkU32(extend_s_10to32(imm)))));
+
+               break;
+
+            case 0x2F:  /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
+               DIP("snei r%u, r%u, %u", regRt, regRs, imm);
+
+               if (mode64)
+                  putIReg(regRt, unop(Iop_1Uto64,
+                                      binop(Iop_CmpNE64,
+                                            getIReg(regRs),
+                                            mkU64(extend_s_10to64(imm)))));
+               else
+                  putIReg(regRt, unop(Iop_1Uto32,
+                                      binop(Iop_CmpNE32,
+                                            getIReg(regRs),
+                                            mkU32(extend_s_10to32(imm)))));
+
+               break;
+
+            default:
+               return False;
+         }
+
+         break;
+      } /* opc1 0x1C ends here*/
+
+      case 0x1F: {
+         switch (opc2) {
+            case 0x0A: {  // lx - Load indexed instructions
+               switch (get_sa(theInstr)) {
+                  case 0x00: {  // LWX rd, index(base)
+                     DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
+                     LOADX_STORE_PATTERN;
+                     putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
+                                                  True));
+                     break;
+                  }
 
-               assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
-                                  unop(Iop_F32toF64, getFReg(ft))));
-               /* Map compare result from IR to MIPS
-                  FP cmp result | MIPS | IR
-                  --------------------------
-                  UN            | 0x1 | 0x45
-                  EQ            | 0x2 | 0x40
-                  GT            | 0x4 | 0x00
-                  LT            | 0x8 | 0x01
-                */
+                  case 0x04:  // LHX rd, index(base)
+                     DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
+                     LOADX_STORE_PATTERN;
 
-               /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
-               assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
-                              binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
-                              binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
-                                    mkU32(2)), binop(Iop_And32,
-                              binop(Iop_Xor32, mkexpr(ccIR),
-                              binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
-                              mkU32(1))))));
-               /* UN */
-               assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
-               /* EQ */
-               assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                      mkU8(0x1)), mkU32(0x1)));
-               /* NGT */
-               assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
-                      mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
-               /* LT */
-               assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                      mkU8(0x3)), mkU32(0x1)));
+                     if (mode64)
+                        putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
+                                                              mkexpr(t1))));
+                     else
+                        putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
+                                                              mkexpr(t1))));
 
-               switch (cond) {
-                  case 0x0:
-                     setFPUCondCode(mkU32(0), fpc_cc);
-                     break;
-                  case 0x1:
-                     setFPUCondCode(mkexpr(t0), fpc_cc);
-                     break;
-                  case 0x2:
-                     setFPUCondCode(mkexpr(t1), fpc_cc);
-                     break;
-                  case 0x3:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                          fpc_cc);
-                     break;
-                  case 0x4:
-                     setFPUCondCode(mkexpr(t3), fpc_cc);
-                     break;
-                  case 0x5:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                          fpc_cc);
-                     break;
-                  case 0x6:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                          fpc_cc);
-                     break;
-                  case 0x7:
-                     setFPUCondCode(mkexpr(t2), fpc_cc);
-                     break;
-                  case 0x8:
-                     setFPUCondCode(mkU32(0), fpc_cc);
-                     break;
-                  case 0x9:
-                     setFPUCondCode(mkexpr(t0), fpc_cc);
-                     break;
-                  case 0xA:
-                     setFPUCondCode(mkexpr(t1), fpc_cc);
                      break;
-                  case 0xB:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                          fpc_cc);
+
+                  case 0x08: {  // LDX rd, index(base)
+                     DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
+                     vassert(mode64); /* Currently Implemented only for n64 */
+                     LOADX_STORE_PATTERN;
+                     putIReg(regRd, load(Ity_I64, mkexpr(t1)));
                      break;
-                  case 0xC:
-                     setFPUCondCode(mkexpr(t3), fpc_cc);
+                  }
+
+                  case 0x06: {  // LBUX rd, index(base)
+                     DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
+                     LOADX_STORE_PATTERN;
+
+                     if (mode64)
+                        putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
+                                                             mkexpr(t1))));
+                     else
+                        putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
+                                                             mkexpr(t1))));
+
                      break;
-                  case 0xD:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                          fpc_cc);
+                  }
+
+                  case 0x10: {  // LWUX rd, index(base) (Cavium OCTEON)
+                     DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
+                     LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
+                     putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
+                                                  False));
                      break;
-                  case 0xE:
-                     setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                          fpc_cc);
+                  }
+
+                  case 0x14: {  // LHUX rd, index(base) (Cavium OCTEON)
+                     DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
+                     LOADX_STORE_PATTERN;
+
+                     if (mode64)
+                        putIReg(regRd,
+                                unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
+                     else
+                        putIReg(regRd,
+                                unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
+
                      break;
-                  case 0xF:
-                     setFPUCondCode(mkexpr(t2), fpc_cc);
+                  }
+
+                  case 0x16: {  // LBX rd, index(base) (Cavium OCTEON)
+                     DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
+                     LOADX_STORE_PATTERN;
+
+                     if (mode64)
+                        putIReg(regRd,
+                                unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
+                     else
+                        putIReg(regRd,
+                                unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
+
                      break;
+                  }
 
                   default:
+                     vex_printf("\nUnhandled LX instruction opc3 = %x\n",
+                                get_sa(theInstr));
                      return False;
                }
-            }
-         }
-            break;
-
-         case 0x11: {  /* C.cond.D */
-            DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
-            t0 = newTemp(Ity_I32);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I32);
-            assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-            /* Map compare result from IR to MIPS
-               FP cmp result | MIPS | IR
-               --------------------------
-               UN            | 0x1 | 0x45
-               EQ            | 0x2 | 0x40
-               GT            | 0x4 | 0x00
-               LT            | 0x8 | 0x01
-             */
-
-            /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
-            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
-                           binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
-                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
-                           binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
-                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
-                           mkU32(1))))));
-
-            /* UN */
-            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
-            /* EQ */
-            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                   mkU8(0x1)), mkU32(0x1)));
-            /* NGT */
-            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
-                   mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
-            /* LT */
-            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
-                   mkU8(0x3)), mkU32(0x1)));
 
-            switch (cond) {
-               case 0x0:
-                  setFPUCondCode(mkU32(0), fpc_cc);
-                  break;
-               case 0x1:
-                  setFPUCondCode(mkexpr(t0), fpc_cc);
-                  break;
-               case 0x2:
-                  setFPUCondCode(mkexpr(t1), fpc_cc);
-                  break;
-               case 0x3:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                       fpc_cc);
-                  break;
-               case 0x4:
-                  setFPUCondCode(mkexpr(t3), fpc_cc);
-                  break;
-               case 0x5:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                       fpc_cc);
-                  break;
-               case 0x6:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                       fpc_cc);
-                  break;
-               case 0x7:
-                  setFPUCondCode(mkexpr(t2), fpc_cc);
-                  break;
-               case 0x8:
-                  setFPUCondCode(mkU32(0), fpc_cc);
-                  break;
-               case 0x9:
-                  setFPUCondCode(mkexpr(t0), fpc_cc);
-                  break;
-               case 0xA:
-                  setFPUCondCode(mkexpr(t1), fpc_cc);
-                  break;
-               case 0xB:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
-                                       fpc_cc);
-                  break;
-               case 0xC:
-                  setFPUCondCode(mkexpr(t3), fpc_cc);
-                  break;
-               case 0xD:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
-                                       fpc_cc);
-                  break;
-               case 0xE:
-                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
-                                       fpc_cc);
-                  break;
-               case 0xF:
-                  setFPUCondCode(mkexpr(t2), fpc_cc);
-                  break;
-               default:
-                  return False;
+               break;
             }
-         }
+         } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
+
          break;
+      } /* opc1 = 0x1F ends here*/
 
-         default:
-            return False;
-      }
-   } else {
-      return False;
-   }
+      default:
+         return False;
+   } /* main opc1 switch ends here */
 
    return True;
 }
 
-/*********************************************************/
-/*---        Branch Instructions for mips64           ---*/
-/*********************************************************/
-static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
-                               Bool(*resteerOkFn) (void *, Addr),
-                               void *callback_opaque, IRStmt ** set )
+static Int msa_I8_logical(UInt cins, UChar wd, UChar ws)
 {
-   UInt jmpKind = 0;
-   UChar opc1 = get_opcode(theInstr);
-   UChar regRs = get_rs(theInstr);
-   UChar regRt = get_rt(theInstr);
-   UInt offset = get_imm(theInstr);
-   Long sOffset = extend_s_16to64(offset);
-   IRType ty = mode64 ? Ity_I64 : Ity_I32;
-   IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
+   IRTemp t1, t2;
+   UShort operation;
+   UChar i8;
+
+   operation = (cins >> 24) & 3;
+   i8 = (cins & 0x00FF0000) >> 16;
+
+   switch (operation) {
+      case 0x00: {  /* ANDI.B */
+         DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t1, getWReg(ws));
+         assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
+         break;
+      }
+
+      case 0x01: { /* ORI.B */
+         DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t1, getWReg(ws));
+         assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         break;
+      }
 
-   IRTemp tmp = newTemp(ty);
-   IRTemp tmpRs = newTemp(ty);
-   IRTemp tmpRt = newTemp(ty);
-   IRTemp tmpLt = newTemp(ty);
-   IRTemp tmpReg0 = newTemp(ty);
+      case 0x02: { /* NORI.B */
+         DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t1, getWReg(ws));
+         assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
+                                             mkexpr(t1), mkexpr(t2))));
+         break;
+      }
 
-   UChar regLnk = 31;   /* reg 31 is link reg in MIPS */
-   Addr64 addrTgt = 0;
-   Addr64 cia = guest_PC_curr_instr;
+      case 0x03: {  /* XORI.B */
+         DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t1, getWReg(ws));
+         assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+         break;
+      }
 
-   IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
-   IRExpr *eNia = mkSzImm(ty, cia + 8);
-   IRExpr *eCond = NULL;
+      default:
+         return -1;
+   }
 
-   assign(tmpRs, getIReg(regRs));
-   assign(tmpRt, getIReg(regRt));
-   assign(tmpReg0, getIReg(0));
+   return 0;
+}
 
-   eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
+static Int msa_I8_branch(UInt cins, UChar wd, UChar ws)
+{
+   IRTemp t1, t2, t3, t4;
+   UShort operation;
+   UChar i8;
 
-   switch (opc1) {
-      case 0x01:
-         switch (regRt) {
-            case 0x00: {  /* BLTZ rs, offset */
-               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
-               IRTemp tmpLtRes = newTemp(Ity_I1);
+   operation = (cins >> 24) & 3;
+   i8 = (cins & 0x00FF0000) >> 16;
 
-               assign(tmp, eConst0);
-               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
-               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
-                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+   switch (operation) {
+      case 0x00: { /* BMNZI.B */
+         DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         t4 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
+         assign(t2, binop(Iop_AndV128, getWReg(wd),
+                          unop(Iop_NotV128, mkexpr(t4))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-               eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
-                             mkexpr(tmpReg0));
+      case 0x01: { /* BMZI.B */
+         DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         t4 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
+         assign(t2, binop(Iop_AndV128, getWReg(ws),
+                          unop(Iop_NotV128, mkexpr(t4))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-               jmpKind = Ijk_Boring;
-               break;
-            }
+      case 0x02: { /* BSELI.B */
+         DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         t4 = newTemp(Ity_V128);
+         ULong tmp = i8;
+         tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                (tmp << 8);
+         assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
+         assign(t2, binop(Iop_AndV128, getWReg(ws),
+                          unop(Iop_NotV128, getWReg(wd))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-            case 0x01: {  /* BGEZ rs, offset */
-               IRTemp tmpLtRes = newTemp(Ity_I1);
-               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+      default:
+         return -1;
+   }
 
-               assign(tmp, eConst0);
-               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
-               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
-                                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
-               eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
-                                    mkexpr(tmpReg0));
+   return 0;
+}
 
-               jmpKind = Ijk_Boring;
-               break;
-            }
+static Int msa_I8_shift(UInt cins, UChar wd, UChar ws)
+{
+   IRTemp t1, t2;
+   UShort operation;
+   UChar i8;
 
-            case 0x11: {  /* BGEZAL rs, offset */
-               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
-               putIReg(regLnk, eNia);
-               IRTemp tmpLtRes = newTemp(Ity_I1);
+   operation = (cins >> 24) & 3;
+   i8 = (cins & 0x00FF0000) >> 16;
 
-               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
-               assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
-                                      unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+   switch (operation) {
+      case 0x00: { /* SHF.B */
+         DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(wd));
+         assign(t2, getWReg(ws));
+         Int i;
+         IRTemp tmp[16];
 
-               eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
-                                    mkexpr(tmpReg0));
+         for (i = 0; i < 16; i++) {
+            tmp[i] = newTemp(Ity_I8);
+            assign(tmp[i],
+                   binop(Iop_GetElem8x16, mkexpr(t2),
+                         mkU8(i - (i % 4) +
+                              ((i8 >> (i % 4) * 2) & 0x03))));
+         }
 
-               jmpKind = Ijk_Call;
-               break;
-            }
+         putWReg(wd, binop(Iop_64HLtoV128,
+                           binop(Iop_32HLto64,
+                                 binop(Iop_16HLto32,
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[15]),
+                                             mkexpr(tmp[14])),
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[13]),
+                                             mkexpr(tmp[12]))),
+                                 binop(Iop_16HLto32,
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[11]),
+                                             mkexpr(tmp[10])),
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[9]),
+                                             mkexpr(tmp[8])))),
+                           binop(Iop_32HLto64,
+                                 binop(Iop_16HLto32,
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[7]),
+                                             mkexpr(tmp[6])),
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[5]),
+                                             mkexpr(tmp[4]))),
+                                 binop(Iop_16HLto32,
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[3]),
+                                             mkexpr(tmp[2])),
+                                       binop(Iop_8HLto16,
+                                             mkexpr(tmp[1]),
+                                             mkexpr(tmp[0]))))));
+         break;
+      }
 
-            case 0x10: {  /* BLTZAL rs, offset */
-               IRTemp tmpLtRes = newTemp(Ity_I1);
-               IRTemp tmpRes = newTemp(ty);
+      case 0x01: { /* SHF.H */
+         DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(wd));
+         assign(t2, getWReg(ws));
+         Int i;
+         IRTemp tmp[8];
 
-               addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
-               putIReg(regLnk, eNia);
+         for (i = 0; i < 8; i++) {
+            tmp[i] = newTemp(Ity_I16);
+            assign(tmp[i],
+                   binop(Iop_GetElem16x8, mkexpr(t2),
+                         mkU8(i - (i % 4) +
+                              ((i8 >> (i % 4) * 2) & 0x03))));
+         }
 
-               assign(tmp, eConst0);
-               assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
-               assign(tmpRes, mode64 ? unop(Iop_1Uto64,
-                      mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
-               eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
-                                                     mkexpr(tmpReg0));
+         putWReg(wd, binop(Iop_64HLtoV128,
+                           binop(Iop_32HLto64,
+                                 binop(Iop_16HLto32,
+                                       mkexpr(tmp[7]), mkexpr(tmp[6])),
+                                 binop(Iop_16HLto32,
+                                       mkexpr(tmp[5]), mkexpr(tmp[4]))),
+                           binop(Iop_32HLto64,
+                                 binop(Iop_16HLto32,
+                                       mkexpr(tmp[3]), mkexpr(tmp[2])),
+                                 binop(Iop_16HLto32,
+                                       mkexpr(tmp[1]), mkexpr(tmp[0])))));
+         break;
+      }
 
-               jmpKind = Ijk_Call;
-               break;
-            }
+      case 0x02: { /* SHF.W */
+         DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(wd));
+         assign(t2, getWReg(ws));
+         Int i;
+         IRTemp tmp[4];
 
+         for (i = 0; i < 4; i++) {
+            tmp[i] = newTemp(Ity_I32);
+            assign(tmp[i],
+                   binop(Iop_GetElem32x4, mkexpr(t2),
+                         mkU8(i - (i % 4) +
+                              ((i8 >> (i % 4) * 2) & 0x03))));
          }
+
+         putWReg(wd, binop(Iop_64HLtoV128,
+                           binop(Iop_32HLto64,
+                                 mkexpr(tmp[3]), mkexpr(tmp[2])),
+                           binop(Iop_32HLto64,
+                                 mkexpr(tmp[1]), mkexpr(tmp[0]))));
          break;
-      default:
-         return False;
       }
-   *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
-   return True;
-}
 
-/*********************************************************/
-/*---         Cavium Specific Instructions            ---*/
-/*********************************************************/
+      default:
+         return -1;
+   }
 
-/* Convenience function to yield to thread scheduler */
-static void jump_back(IRExpr *condition)
-{
-   stmt( IRStmt_Exit(condition,
-                     Ijk_Yield,
-                     IRConst_U64( guest_PC_curr_instr ),
-                     OFFB_PC) );
+   return 0;
 }
 
-/* Based on s390_irgen_load_and_add32. */
-static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
-                              IRTemp expd, UChar rd, Bool putIntoRd)
+static Int msa_I5_06(UInt cins, UChar wd, UChar ws)   /* I5 (0x06) */
 {
-   IRCAS *cas;
-   IRTemp old_mem = newTemp(Ity_I32);
-   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
+   IRTemp t1, t2, t3;
+   UShort operation;
+   UChar df, wt;
 
-   cas = mkIRCAS(IRTemp_INVALID, old_mem,
-#if defined (_MIPSEL)
-                 Iend_LE, mkexpr(op1addr),
-#else /* _MIPSEB */
-                 Iend_BE, mkexpr(op1addr),
-#endif
-                 NULL, mkexpr(expd), /* expected value */
-                 NULL, mkexpr(new_val)  /* new value */);
-   stmt(IRStmt_CAS(cas));
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
-   /* If old_mem contains the expected value, then the CAS succeeded.
-      Otherwise, it did not */
-   jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
-   if (putIntoRd)
-      putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
-}
+   switch (operation) {
+      case 0x00: { /* ADDVI */
+         ULong tmp = wt;
 
-/* Based on s390_irgen_load_and_add64. */
-static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
-                              IRTemp expd, UChar rd, Bool putIntoRd)
-{
-   IRCAS *cas;
-   IRTemp old_mem = newTemp(Ity_I64);
-   vassert(mode64);
-   cas = mkIRCAS(IRTemp_INVALID, old_mem,
-#if defined (_MIPSEL)
-                 Iend_LE, mkexpr(op1addr),
-#else /* _MIPSEB */
-                 Iend_BE, mkexpr(op1addr),
-#endif
-                 NULL, mkexpr(expd), /* expected value */
-                 NULL, mkexpr(new_val)  /* new value */);
-   stmt(IRStmt_CAS(cas));
+         switch (df) {
+            case 0x00: { /* ADDVI.B */
+               DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-   /* If old_mem contains the expected value, then the CAS succeeded.
-      Otherwise, it did not */
-   jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
-   if (putIntoRd)
-      putIReg(rd, mkexpr(old_mem));
-}
+            case 0x01: { /* ADDVI.H */
+               DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-static Bool dis_instr_CVM ( UInt theInstr )
-{
-   UChar  opc2     = get_function(theInstr);
-   UChar  opc1     = get_opcode(theInstr);
-   UChar  regRs    = get_rs(theInstr);
-   UChar  regRt    = get_rt(theInstr);
-   UChar  regRd    = get_rd(theInstr);
-   /* MIPS trap instructions extract code from theInstr[15:6].
-      Cavium OCTEON instructions SNEI, SEQI extract immediate operands
-      from the same bit field [15:6]. */
-   UInt   imm      = get_code(theInstr);
-   UChar  lenM1    = get_msb(theInstr);
-   UChar  p        = get_lsb(theInstr);
-   IRType ty       = mode64? Ity_I64 : Ity_I32;
-   IRTemp tmp      = newTemp(ty);
-   IRTemp tmpRs    = newTemp(ty);
-   IRTemp tmpRt    = newTemp(ty);
-   IRTemp t1       = newTemp(ty);
-   UInt size;
-   assign(tmpRs, getIReg(regRs));
+            case 0x02: { /* ADDVI.W */
+               DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-   switch(opc1) {
-      case 0x1C: {
-         switch(opc2) { 
-            case 0x03: {  /* DMUL rd, rs, rt */
-               DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
-               IRTemp t0 = newTemp(Ity_I128);
-               assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
-               putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
+            case 0x03: { /* ADDVI.D */
+               DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+         }
+
+         break;
+      }
+
+      case 0x01: { /* SUBVI */
+         ULong tmp = wt;
+
+         switch (df) {
+            case 0x00: { /* SUBVI.B */
+               DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x18: {  /* Store Atomic Add Word - SAA; Cavium OCTEON */
-               DIP("saa r%u, (r%u)", regRt, regRs);
-               IRTemp addr = newTemp(Ity_I64);
-               IRTemp new_val = newTemp(Ity_I32);
-               IRTemp old = newTemp(Ity_I32);
-               assign(addr, getIReg(regRs));
-               assign(old, load(Ity_I32, mkexpr(addr)));
-               assign(new_val, binop(Iop_Add32,
-                                     mkexpr(old),
-                                     mkNarrowTo32(ty, getIReg(regRt))));
-               mips_load_store32(addr, new_val, old, 0, False);
+            case 0x01: { /* SUBVI.H */
+               DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
-            case 0x19: {
-               DIP( "saad r%u, (r%u)", regRt, regRs);
-               IRTemp addr = newTemp(Ity_I64);
-               IRTemp new_val = newTemp(Ity_I64);
-               IRTemp old = newTemp(Ity_I64);
-               assign(addr, getIReg(regRs));
-               assign(old, load(Ity_I64, mkexpr(addr)));
-               assign(new_val, binop(Iop_Add64,
-                                     mkexpr(old),
-                                     getIReg(regRt)));
-               mips_load_store64(addr, new_val, old, 0, False);
+            case 0x02: { /* SUBVI.W */
+               DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            /* LAI, LAID, LAD, LADD, LAS, LASD,
-               LAC, LACD, LAA, LAAD, LAW, LAWD */
-            case 0x1f: {
-               UInt opc3 = get_sa(theInstr);
-               IRTemp addr = newTemp(Ity_I64);
-               switch (opc3) {
-                  /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
-                  case 0x02: {
-                     DIP("lai r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Add32,
-                                           mkexpr(old),
-                                           mkU32(1)));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
-                  case 0x03: {
-                     DIP("laid r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Add64,
-                                           mkexpr(old),
-                                           mkU64(1)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
-                  case 0x06: {
-                     DIP("lad r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Sub32,
-                                           mkexpr(old),
-                                           mkU32(1)));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
-                  case 0x07: {
-                     DIP("ladd r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Sub64,
-                                           mkexpr(old),
-                                           mkU64(1)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
-                  case 0x0a: {
-                     DIP("las r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, mkU32(0xffffffff));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
-                  case 0x0b: {
-                     DIP("lasd r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, mkU64(0xffffffffffffffffULL));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
-                  case 0x0e: {
-                     DIP("lac r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, mkU32(0));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
-                  case 0x0f: {
-                     DIP("lacd r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, mkU64(0));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
-                  case 0x12: {
-                     DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Add32,
-                                           mkexpr(old),
-                                           mkNarrowTo32(ty, getIReg(regRt))));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
-                  case 0x13: {
-                     DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     assign(new_val, binop(Iop_Add64,
-                                           load(Ity_I64, mkexpr(addr)),
-                                           getIReg(regRt)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
-                  case 0x16: {
-                     DIP("law r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I32);
-                     IRTemp old = newTemp(Ity_I32);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
-                     assign(old, load(Ity_I32, mkexpr(addr)));
-                     mips_load_store32(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
-                  case 0x17: {
-                     DIP("lawd r%u,(r%u)\n", regRd, regRs);
-                     IRTemp new_val = newTemp(Ity_I64);
-                     IRTemp old = newTemp(Ity_I64);
-                     assign(addr, getIReg(regRs));
-                     assign(new_val, getIReg(regRt));
-                     assign(old, load(Ity_I64, mkexpr(addr)));
-                     mips_load_store64(addr, new_val, old, regRd, True);
-                     break;
-                  }
-                  default:
-                     vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
-                     vex_printf("Instruction=0x%08x\n", theInstr);
-                     return False;
-               }
+            case 0x03: { /* SUBVI.D */
+               DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
+         }
 
-            /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
-            case 0x28: {
-               DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
-               IRTemp t0 = newTemp(Ity_I8);
-               assign(t0, binop(Iop_Add8,
-                                mkNarrowTo8(ty, getIReg(regRs)),
-                                mkNarrowTo8(ty, getIReg(regRt))));
-               if (mode64)
-                  putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
-                                       unop(Iop_8Uto64, mkexpr(t0)),
-                                       mkSzImm(ty, 0xFF)));
-               else
-                  putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
-                                       unop(Iop_8Uto32, mkexpr(t0)),
-                                       mkSzImm(ty, 0xFF)));
+         break;
+      }
+
+      case 0x02: { /* MAXI_S */
+         ULong tmp = wt;
+
+         switch (df) {
+            case 0x00: { /* MAXI_S.B */
+               DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               char stemp = ((int)tmp << 27) >> 27;
+               tmp = (UChar)stemp;
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-            case 0x2c: {  /* Count Ones in a Word - POP; Cavium OCTEON */
-               int i, shift[5];
-               IRTemp mask[5];
-               IRTemp old = newTemp(ty);
-               IRTemp nyu = IRTemp_INVALID;
-               assign(old, getIReg(regRs));
-               DIP("pop r%u, r%u", regRd, regRs);
-               for (i = 0; i < 5; i++) {
-                  mask[i] = newTemp(ty);
-                  shift[i] = 1 << i;
-               }
-               if(mode64) {
-                  assign(mask[0], mkU64(0x0000000055555555));
-                  assign(mask[1], mkU64(0x0000000033333333));
-                  assign(mask[2], mkU64(0x000000000F0F0F0F));
-                  assign(mask[3], mkU64(0x0000000000FF00FF));
-                  assign(mask[4], mkU64(0x000000000000FFFF));
-  
-                  for (i = 0; i < 5; i++) {
-                     nyu = newTemp(ty);
-                     assign(nyu,
-                            binop(Iop_Add64,
-                                  binop(Iop_And64,
-                                        mkexpr(old), mkexpr(mask[i])),
-                                  binop(Iop_And64,
-                                        binop(Iop_Shr64,
-                                              mkexpr(old), mkU8(shift[i])),
-                                        mkexpr(mask[i]))));
-                     old = nyu;
-                  }
-               } else {
-                  assign(mask[0], mkU32(0x55555555));
-                  assign(mask[1], mkU32(0x33333333));
-                  assign(mask[2], mkU32(0x0F0F0F0F));
-                  assign(mask[3], mkU32(0x00FF00FF));
-                  assign(mask[4], mkU32(0x0000FFFF));
-                  assign(old, getIReg(regRs));
-                  for (i = 0; i < 5; i++) {
-                     nyu = newTemp(ty);
-                     assign(nyu,
-                            binop(Iop_Add32,
-                                  binop(Iop_And32,
-                                        mkexpr(old), mkexpr(mask[i])),
-                                  binop(Iop_And32,
-                                        binop(Iop_Shr32,
-                                              mkexpr(old), mkU8(shift[i])),
-                                        mkexpr(mask[i]))));
-                     old = nyu;
-                  }
-               }
-               putIReg(regRd, mkexpr(nyu));
+
+            case 0x01: { /* MAXI_S.H */
+               DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               short stemp = ((int)tmp << 27) >> 27;
+               tmp = (UShort)stemp;
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* MAXI_S.W */
+               DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               int stemp = ((int)tmp << 27) >> 27;
+               tmp = (UInt)stemp;
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* MAXI_S.D */
+               DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               Long stemp = ((Long)tmp << 59) >> 59;
+               tmp = stemp;
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-            /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
-            case 0x2d: {
-               int i, shift[6];
-               IRTemp mask[6];
-               IRTemp old = newTemp(ty);
-               IRTemp nyu = IRTemp_INVALID;
-               DIP("dpop r%u, r%u", regRd, regRs);
-               for (i = 0; i < 6; i++) {
-                  mask[i] = newTemp(ty);
-                  shift[i] = 1 << i;
-               }
-               vassert(mode64); /*Caution! Only for Mode 64*/
-               assign(mask[0], mkU64(0x5555555555555555ULL));
-               assign(mask[1], mkU64(0x3333333333333333ULL));
-               assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
-               assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
-               assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
-               assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
-               assign(old, getIReg(regRs));
-               for (i = 0; i < 6; i++) {
-                  nyu = newTemp(Ity_I64);
-                  assign(nyu,
-                         binop(Iop_Add64,
-                               binop(Iop_And64,
-                                     mkexpr(old), mkexpr(mask[i])),
-                               binop(Iop_And64,
-                                     binop(Iop_Shr64,
-                                           mkexpr(old), mkU8(shift[i])),
-                                     mkexpr(mask[i]))));
-                  old = nyu;
-               }
-               putIReg(regRd, mkexpr(nyu));
+         }
+
+         break;
+      }
+
+      case 0x03: { /* MAXI_U */
+         ULong tmp = wt;
+
+         switch (df) {
+            case 0x00: { /* MAXI_U.B */
+               DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x32:  /* 5. CINS rd, rs, p, lenm1 */
-               DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1); 
-               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
-                                     mkU8(64-( lenM1+1 ))));
-               assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
-                                     mkU8(64-(p+lenM1+1))));
-               putIReg( regRt, mkexpr(tmpRt));
+            case 0x01: { /* MAXI_U.H */
+               DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            case 0x33:  /* 6. CINS32 rd, rs, p+32, lenm1 */
-               DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1);
-               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
-                                     mkU8(64-( lenM1+1 ))));
-               assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
-                                     mkU8(32-(p+lenM1+1))));
-               putIReg( regRt, mkexpr(tmpRt));
+            case 0x02: { /* MAXI_U.W */
+               DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            case 0x3A:  /* 3. EXTS rt, rs, p len */
-               DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 
-               size = lenM1 + 1;  /* lenm1+1 */
-               UChar lsAmt = 64 - (p + size);  /* p+lenm1+1 */
-               UChar rsAmt = 64 - size;  /* lenm1+1 */
-               tmp = newTemp(Ity_I64);
-               assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
-               putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
+            case 0x03: { /* MAXI_U.D */
+               DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
+         }
 
-            case 0x3B:  /* 4. EXTS32 rt, rs, p len */
-               DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 
-               assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
-                                     mkU8(32-(p+lenM1+1))));
-               assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
-                                     mkU8(64-(lenM1+1))) );
-               putIReg( regRt, mkexpr(tmpRt));
+         break;
+      }
+
+      case 0x04: { /* MINI_S */
+         ULong tmp = wt;
+
+         switch (df) {
+            case 0x00: { /* MINI_S.B */
+               DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               char stemp = ((int)tmp << 27) >> 27;
+               tmp = (UChar)stemp;
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            case 0x2B:  /* 20. SNE rd, rs, rt */
-               DIP("sne r%u, r%u, r%u", regRd,regRs, regRt);
-               if (mode64)
-                  putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
-                                                        getIReg(regRs),
-                                                        getIReg(regRt))));
-               else
-                  putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32,
-                                                       getIReg(regRs),
-                                                       getIReg(regRt))));
+            case 0x01: { /* MINI_S.H */
+               DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               short stemp = ((int)tmp << 27) >> 27;
+               tmp = (UShort)stemp;
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            case 0x2A:  /* Set Equals - SEQ; Cavium OCTEON */
-               DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
-               if (mode64)
-                  putIReg(regRd, unop(Iop_1Uto64,
-                                      binop(Iop_CmpEQ64, getIReg(regRs),
-                                            getIReg(regRt))));
-               else
-                  putIReg(regRd, unop(Iop_1Uto32,
-                                      binop(Iop_CmpEQ32, getIReg(regRs),
-                                            getIReg(regRt))));
+            case 0x02: { /* MINI_S.W */
+               DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               int stemp = ((int)tmp << 27) >> 27;
+               tmp = (UInt)stemp;
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            case 0x2E:  /* Set Equals Immediate - SEQI; Cavium OCTEON */
-               DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
-               if (mode64)
-                  putIReg(regRt, unop(Iop_1Uto64,
-                                      binop(Iop_CmpEQ64, getIReg(regRs),
-                                            mkU64(extend_s_10to64(imm)))));
-               else
-                  putIReg(regRt, unop(Iop_1Uto32,
-                                      binop(Iop_CmpEQ32, getIReg(regRs),
-                                            mkU32(extend_s_10to32(imm)))));
+            case 0x03: { /* MINI_S.D */
+               DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               Long stemp = ((Long)tmp << 59) >> 59;
+               tmp = stemp;
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
+         }
 
-            case 0x2F:  /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
-               DIP("snei r%u, r%u, %u", regRt, regRs, imm);
-               if (mode64)
-                  putIReg(regRt, unop(Iop_1Uto64,
-                                   binop(Iop_CmpNE64,
-                                         getIReg(regRs),
-                                         mkU64(extend_s_10to64(imm)))));
-               else
-                  putIReg(regRt, unop(Iop_1Uto32,
-                                   binop(Iop_CmpNE32,
-                                         getIReg(regRs),
-                                         mkU32(extend_s_10to32(imm)))));
+         break;
+      }
+
+      case 0x05: { /* MINI_U */
+         ULong tmp = wt;
+
+         switch (df) {
+            case 0x00: { /* MINI_U.B */
+               DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
+            }
 
-            default:
-               return False;
+            case 0x01: { /* MINI_U.H */
+               DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* MINI_U.W */
+               DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* MINI_U.D */
+               DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
          }
+
          break;
-      } /* opc1 0x1C ends here*/
-      case 0x1F: {
-         switch(opc2) {
-            case 0x0A: {  // lx - Load indexed instructions
-               switch (get_sa(theInstr)) {
-                  case 0x00: {  // LWX rd, index(base)
-                     DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
-                     LOADX_STORE_PATTERN;
-                     putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
-                                                  True));
-                     break;
-                  }
-                  case 0x04:  // LHX rd, index(base)
-                     DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
-                     LOADX_STORE_PATTERN;
-                     if (mode64)
-                        putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
-                                                              mkexpr(t1))));
-                     else
-                        putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
-                                                              mkexpr(t1))));
-                     break;
-                  case 0x08: {  // LDX rd, index(base)
-                     DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
-                     vassert(mode64); /* Currently Implemented only for n64 */
-                     LOADX_STORE_PATTERN;
-                     putIReg(regRd, load(Ity_I64, mkexpr(t1)));
-                     break;
-                  }
-                  case 0x06: {  // LBUX rd, index(base)
-                     DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
-                     LOADX_STORE_PATTERN;
-                     if (mode64)
-                        putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
-                                                             mkexpr(t1))));
-                     else
-                        putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
-                                                             mkexpr(t1))));
-                     break;
-                  }
-                  case 0x10: {  // LWUX rd, index(base) (Cavium OCTEON)
-                     DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
-                     LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
-                     putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
-                                                  False));
-                     break;
-                  }
-                  case 0x14: {  // LHUX rd, index(base) (Cavium OCTEON)
-                     DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
-                     LOADX_STORE_PATTERN;
-                     if (mode64)
-                        putIReg(regRd,
-                                unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
-                     else
-                        putIReg(regRd,
-                                unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
-                     break;
-                  }
-                  case 0x16: {  // LBX rd, index(base) (Cavium OCTEON)
-                     DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
-                     LOADX_STORE_PATTERN;
-                     if (mode64)
-                        putIReg(regRd,
-                                unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
-                     else
-                        putIReg(regRd,
-                                unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
-                     break;
-                  }
-                  default:
-                     vex_printf("\nUnhandled LX instruction opc3 = %x\n",
-                                get_sa(theInstr));
-                     return False;
-               }
+      }
+
+      default: {
+         return -1;
+      }
+   }
+
+   return 0;
+}
+
+static Int msa_I5_07(UInt cins, UChar wd, UChar ws)   /* I5 (0x07) / I10 */
+{
+   IRTemp t1, t2, t3;
+   UShort operation;
+   UChar df, i5;
+
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x00600000) >> 21;
+   i5 = (cins & 0x001F0000) >> 16;
+
+   switch (operation) {
+      case 0x00: {
+         ULong tmp = i5;
+
+         switch (df) {
+            case 0x00: { /* CEQI.B */
+               DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               char stemp = ((int)tmp << 27) >> 27;
+               tmp = (UChar)stemp;
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-         } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
+
+            case 0x01: { /* CEQI.H */
+               DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               short stemp = ((int)tmp << 27) >> 27;
+               tmp = (UShort)stemp;
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* CEQI.W */
+               DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               int stemp = ((int)tmp << 27) >> 27;
+               tmp = (UInt)stemp;
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* CEQI.D */
+               DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               Long stemp = ((Long)tmp << 59) >> 59;
+               tmp = stemp;
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+         }
+
          break;
-      } /* opc1 = 0x1F ends here*/
-      default:
-         return False; 
-   } /* main opc1 switch ends here */
-   return True;
-}
+      }
 
-/*------------------------------------------------------------*/
-/*---       Disassemble a single DSP ASE instruction       ---*/
-/*------------------------------------------------------------*/
+      case 0x02: { /* CLTI_S.df */
+         ULong tmp = i5;
 
-static UInt disDSPInstr_MIPS_WRK ( UInt cins )
-{
-   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
-          t15, t16, t17;
-   UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
-        wrdsp_mask, dsp_imm, shift;
+         switch (df) {
+            case 0x00: { /* CLTI_S.B */
+               DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               char stemp = ((int)tmp << 27) >> 27;
+               tmp = (UChar)stemp;
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-   opcode = get_opcode(cins);
-   rs = get_rs(cins);
-   rt = get_rt(cins);
-   rd = get_rd(cins);
-   sa = get_sa(cins);
-   function = get_function(cins);
-   ac = get_acNo(cins);
-   ac_mfhilo = get_acNo_mfhilo(cins);
-   rddsp_mask = get_rddspMask(cins);
-   wrdsp_mask = get_wrdspMask(cins);
-   dsp_imm = get_dspImm(cins);
-   shift = get_shift(cins);
-
-   switch (opcode) {
-      case 0x00: {  /* Special */
-         switch (function) {
-            case 0x10: {  /* MFHI */
-               DIP("mfhi ac%u r%u", ac_mfhilo, rd);
-               putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
+            case 0x01: { /* CLTI_S.H */
+               DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               short stemp = ((int)tmp << 27) >> 27;
+               tmp = (UShort)stemp;
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* CLTI_S.W */
+               DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               int stemp = ((int)tmp << 27) >> 27;
+               tmp = (UInt)stemp;
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x11: {  /* MTHI */
-               DIP("mthi ac%u r%u", ac, rs);
-               t1 = newTemp(Ity_I32);
-               assign(t1, unop(Iop_64to32, getAcc(ac)));
-               putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
+            case 0x03: { /* CLTI_S.D */
+               DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               Long stemp = ((Long)tmp << 59) >> 59;
+               tmp = stemp;
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x12: {  /* MFLO */
-               DIP("mflo ac%u r%u", ac_mfhilo, rd);
-               putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x03: { /* CLTI_U.df */
+         ULong tmp = i5;
+
+         switch (df) {
+            case 0x00: { /* CLTI_U.B */
+               DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x13: {  /* MTLO */
-               DIP("mtlo ac%u r%u", ac, rs);
-               t1 = newTemp(Ity_I32);
-               assign(t1, unop(Iop_64HIto32, getAcc(ac)));
-               putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
+            case 0x01: { /* CLTI_U.H */
+               DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x18: {  /* MULT */
-               DIP("mult ac%u r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
-                                mkNarrowTo32(Ity_I32, getIReg(rt))));
-               putAcc(ac, mkexpr(t1));
+            case 0x02: { /* CLTI_U.W */
+               DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
                break;
             }
 
-            case 0x19: {  /* MULTU */
-               DIP("multu ac%u r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
-                                             mkNarrowTo32(Ity_I32,
-                                                          getIReg(rt))));
-               putAcc(ac, mkexpr(t1));
-            break;
+            case 0x03: { /* CLTI_U.D */
+               DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
          }
+
          break;
       }
-      case 0x1C: {  /* Special2 */
-         switch (function) {
-            case 0x00: {  /* MADD */
-               DIP("madd ac%u, r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               t2 = newTemp(Ity_I64);
-               t3 = newTemp(Ity_I64);
 
-               assign(t1, getAcc(ac));
-               assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
-               assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
+      case 0x04: { /* CLEI_S.df */
+         ULong tmp = i5;
 
-               putAcc(ac, mkexpr(t3));
+         switch (df) {
+            case 0x00: { /* CLEI_S.B */
+               DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               char stemp = ((int)tmp << 27) >> 27;
+               tmp = (UChar)stemp;
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
+                                                  mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ8x16,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-            case 0x01: {  /* MADDU */
-               DIP("maddu ac%u r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               t2 = newTemp(Ity_I64);
-               t3 = newTemp(Ity_I64);
 
-               assign(t1, getAcc(ac));
-               assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
-               assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
-
-               putAcc(ac, mkexpr(t3));
+            case 0x01: { /* CLEI_S.H */
+               DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               short stemp = ((int)tmp << 27) >> 27;
+               tmp = (UShort)stemp;
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
+                                                  mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ16x8,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-            case 0x04: {  /* MSUB */
-               DIP("msub ac%u r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               t2 = newTemp(Ity_I64);
-               t3 = newTemp(Ity_I64);
 
-               assign(t1, getAcc(ac));
-               assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
-               assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
-
-               putAcc(ac, mkexpr(t3));
+            case 0x02: { /* CLEI_S.W */
+               DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               int stemp = ((int)tmp << 27) >> 27;
+               tmp = (UInt)stemp;
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT32Sx4,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ32x4,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
                break;
             }
-            case 0x05: {  /* MSUBU */
-               DIP("msubu ac%u r%u, r%u", ac, rs, rt);
-               t1 = newTemp(Ity_I64);
-               t2 = newTemp(Ity_I64);
-               t3 = newTemp(Ity_I64);
 
-               assign(t1, getAcc(ac));
-               assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
-               assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
-
-               putAcc(ac, mkexpr(t3));
+            case 0x03: { /* CLEI_S.D */
+               DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               Long stemp = ((Long)tmp << 59) >> 59;
+               tmp = stemp;
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT64Sx2,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ64x2,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
                break;
             }
+
+            default:
+               return -1;
          }
+
          break;
       }
-      case 0x1F: {  /* Special3 */
-         switch (function) {
-            case 0x12: {  /* ABSQ_S.PH */
-               switch (sa) {
-                  case 0x1: {  /* ABSQ_S.QB */
-                     DIP("absq_s.qb r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I8);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I8);
-                     t8 = newTemp(Ity_I8);
-                     t9 = newTemp(Ity_I1);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I8);
-                     t12 = newTemp(Ity_I8);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I1);
-                     t15 = newTemp(Ity_I8);
-                     t16 = newTemp(Ity_I32);
-                     t17 = newTemp(Ity_I32);
-
-                     /* Absolute value of the rightmost byte (bits 7-0). */
-                     /* t0 - rightmost byte. */
-                     assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
-                     /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32, mkexpr(t0)),
-                                      mkU32(0x00000080)));
-                     /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
-                     assign(t2, unop(Iop_32to1,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 getIReg(rt),
-                                                 mkU32(0x00000080)),
-                                           mkU8(0x7))));
-                     /* t3 holds abs(t0). */
-                     assign(t3, IRExpr_ITE(mkexpr(t1),
-                                           mkU8(0x7F),
-                                           IRExpr_ITE(mkexpr(t2),
-                                                      binop(Iop_Add8,
-                                                            unop(Iop_Not8,
-                                                                 mkexpr(t0)),
-                                                            mkU8(0x1)),
-                                                      mkexpr(t0))));
-
-                     /* Absolute value of bits 15-8. */
-                     /* t4 - input byte. */
-                     assign(t4,
-                            unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
-                     /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32, mkexpr(t4)),
-                                      mkU32(0x00000080)));
-                     /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
-                     assign(t6, unop(Iop_32to1,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 getIReg(rt),
-                                                 mkU32(0x00008000)),
-                                           mkU8(15))));
-                     /* t3 holds abs(t4). */
-                     assign(t7, IRExpr_ITE(mkexpr(t5),
-                                           mkU8(0x7F),
-                                           IRExpr_ITE(mkexpr(t6),
-                                                      binop(Iop_Add8,
-                                                            unop(Iop_Not8,
-                                                                 mkexpr(t4)),
-                                                            mkU8(0x1)),
-                                                      mkexpr(t4))));
-
-                     /* Absolute value of bits 23-15. */
-                     /* t8 - input byte. */
-                     assign(t8,
-                            unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
-                     /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
-                     assign(t9, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32, mkexpr(t8)),
-                                      mkU32(0x00000080)));
-                     /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
-                     assign(t10, unop(Iop_32to1,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0x00800000)),
-                                            mkU8(23))));
-                     /* t3 holds abs(t8). */
-                     assign(t11, IRExpr_ITE(mkexpr(t9),
-                                            mkU8(0x7F),
-                                            IRExpr_ITE(mkexpr(t10),
-                                                       binop(Iop_Add8,
-                                                             unop(Iop_Not8,
-                                                                  mkexpr(t8)),
-                                                             mkU8(0x1)),
-                                                       mkexpr(t8))));
-
-                     /* Absolute value of bits 31-24. */
-                     /* t12 - input byte. */
-                     assign(t12,
-                            unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
-                     /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
-                     assign(t13, binop(Iop_CmpEQ32,
-                                       unop(Iop_8Uto32, mkexpr(t12)),
-                                       mkU32(0x00000080)));
-                     /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
-                     assign(t14, unop(Iop_32to1,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31))));
-                     /* t15 holds abs(t12). */
-                     assign(t15, IRExpr_ITE(mkexpr(t13),
-                                            mkU8(0x7F),
-                                            IRExpr_ITE(mkexpr(t14),
-                                                       binop(Iop_Add8,
-                                                             unop(Iop_Not8,
-                                                                  mkexpr(t12)),
-                                                             mkU8(0x1)),
-                                                       mkexpr(t12))));
-
-                     /* t16 holds !0 if any of input bytes is 0x80 or 0
-                        otherwise. */
-                     assign(t16,
-                            binop(Iop_Or32,
-                                  binop(Iop_Or32,
-                                        binop(Iop_Or32,
-                                              unop(Iop_1Sto32, mkexpr(t13)),
-                                              unop(Iop_1Sto32, mkexpr(t9))),
-                                        unop(Iop_1Sto32, mkexpr(t5))),
-                                  unop(Iop_1Sto32, mkexpr(t1))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    mkexpr(t16),
-                                                    mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000))));
-
-                     /* t17 = t15|t11|t7|t3 */
-                     assign(t17,
-                            binop(Iop_16HLto32,
-                                  binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
-                                  binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
-
-                     putIReg(rd, mkexpr(t17));
-                     break;
-                  }
-                  case 0x2: {  /* REPL.QB */
-                     DIP("repl.qb r%u, %u", rd, dsp_imm);
-                     vassert(!mode64);
 
-                     putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
-                                       (dsp_imm << 8) | (dsp_imm)));
-                     break;
-                  }
-                  case 0x3: {  /* REPLV.QB */
-                     DIP("replv.qb r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I8);
-
-                     assign(t0, unop(Iop_32to8,
-                                binop(Iop_And32, getIReg(rt), mkU32(0xff))));
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
-                                   binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
-                     break;
-                  }
-                  case 0x4: {  /* PRECEQU.PH.QBL */
-                     DIP("precequ.ph.qbl r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0xff000000)),
-                                             mkU8(1)),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x00ff0000)),
-                                             mkU8(9))));
-                     break;
-                  }
-                  case 0x5: {  /* PRECEQU.PH.QBR */
-                     DIP("precequ.ph.qbr r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shl32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x0000ff00)),
-                                             mkU8(15)),
-                                       binop(Iop_Shl32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x000000ff)),
-                                             mkU8(7))));
-                     break;
-                  }
-                  case 0x6: {  /* PRECEQU.PH.QBLA */
-                     DIP("precequ.ph.qbla r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0xff000000)),
-                                             mkU8(1)),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x0000ff00)),
-                                             mkU8(1))));
-                     break;
-                  }
-                  case 0x7: {  /* PRECEQU.PH.QBRA */
-                     DIP("precequ.ph.qbra r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shl32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x00ff0000)),
-                                             mkU8(7)),
-                                       binop(Iop_Shl32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x000000ff)),
-                                             mkU8(7))));
-                     break;
-                  }
-                  case 0x9: {  /* ABSQ_S.PH */
-                     DIP("absq_s.ph r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I16);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I16);
-                     t4 = newTemp(Ity_I16);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I16);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-
-                     /* t0 holds lower 16 bits of value in rt. */
-                     assign(t0, unop(Iop_32to16, getIReg(rt)));
-                     /* t1 holds 1 if t0 is equal to 0x8000. */
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32, mkexpr(t0)),
-                                      mkU32(0x00008000)));
-                     /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
-                     assign(t2, unop(Iop_32to1,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 getIReg(rt),
-                                                 mkU32(0x00008000)),
-                                           mkU8(15))));
-                     /* t3 holds abs(t0). */
-                     assign(t3, IRExpr_ITE(mkexpr(t1),
-                                           mkU16(0x7FFF),
-                                           IRExpr_ITE(mkexpr(t2),
-                                                      binop(Iop_Add16,
-                                                            unop(Iop_Not16,
-                                                                 mkexpr(t0)),
-                                                            mkU16(0x1)),
-                                                      mkexpr(t0))));
-
-                     /* t4 holds lower 16 bits of value in rt. */
-                     assign(t4, unop(Iop_32HIto16, getIReg(rt)));
-                     /* t5 holds 1 if t4 is equal to 0x8000. */
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32, mkexpr(t4)),
-                                      mkU32(0x00008000)));
-                     /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
-                     assign(t6, unop(Iop_32to1,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 getIReg(rt),
-                                                 mkU32(0x80000000)),
-                                           mkU8(31))));
-                     /* t7 holds abs(t4). */
-                     assign(t7, IRExpr_ITE(mkexpr(t5),
-                                           mkU16(0x7FFF),
-                                           IRExpr_ITE(mkexpr(t6),
-                                                      binop(Iop_Add16,
-                                                            unop(Iop_Not16,
-                                                                 mkexpr(t4)),
-                                                            mkU16(0x1)),
-                                                      mkexpr(t4))));
-                     /* If any of the two input halfwords is equal 0x8000,
-                        set bit 20 in DSPControl register. */
-                     assign(t8, binop(Iop_Or32,
-                                      unop(Iop_1Sto32, mkexpr(t5)),
-                                      unop(Iop_1Sto32, mkexpr(t1))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    mkexpr(t8),
-                                                    mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000))));
-
-                     /* t9 = t7|t3 */
-                     assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
-
-                     putIReg(rd, mkexpr(t9));
-                     break;
-                  }
-                  case 0xA: {  /* REPL.PH */
-                     DIP("repl.ph r%u, %u", rd, dsp_imm);
-                     vassert(!mode64);
-                     UShort immediate = extend_s_10to16(dsp_imm);
+      case 0x05: { /* CLEI_U.df */
+         ULong tmp = i5;
 
-                     putIReg(rd, mkU32(immediate << 16 | immediate));
-                     break;
-                  }
-                  case 0xB: {  /* REPLV.PH */
-                     DIP("replv.ph r%u, r%u", rd, rt);
-                     vassert(!mode64);
+         switch (df) {
+            case 0x00: { /* CLEI_U.B */
+               DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT8Ux16,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ8x16,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, getIReg(rt)),
-                                       unop(Iop_32to16, getIReg(rt))));
-                     break;
-                  }
-                  case 0xC: {  /* PRECEQ.W.PHL */
-                     DIP("preceq.w.phl r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     putIReg(rd, binop(Iop_And32,
-                                       getIReg(rt),
-                                       mkU32(0xffff0000)));
-                     break;
-                  }
-                  case 0xD: {  /* PRECEQ.W.PHR */
-                     DIP("preceq.w.phr r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, getIReg(rt)),
-                                       mkU16(0x0)));
-                     break;
-                  }
-                  case 0x11: {  /* ABSQ_S.W */
-                     DIP("absq_s.w r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I1);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-
-                     assign(t0,
-                            binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t0),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
-
-                     assign(t2, IRExpr_ITE(mkexpr(t0),
-                                           mkU32(0x7FFFFFFF),
-                                           IRExpr_ITE(mkexpr(t1),
-                                                      binop(Iop_Add32,
-                                                            unop(Iop_Not32,
-                                                                 getIReg(rt)),
-                                                            mkU32(0x1)),
-                                                      getIReg(rt))));
-                     putIReg(rd, mkexpr(t2));
-                     break;
-                  }
-                  case 0x1B: {  /* BITREV */
-                     DIP("bitrev r%u, r%u", rd, rt);
-                     vassert(!mode64);
-                     /* 32bit reversal as seen on Bit Twiddling Hacks site
-                        http://graphics.stanford.edu/~seander/bithacks.html
-                        section ReverseParallel */
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
+            case 0x01: { /* CLEI_U.H */
+               DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT16Ux8,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ16x8,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     assign(t1, binop(Iop_Or32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0xaaaaaaaa)),
-                                            mkU8(0x1)),
-                                      binop(Iop_Shl32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0x55555555)),
-                                            mkU8(0x1))));
-                     assign(t2, binop(Iop_Or32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t1),
-                                                  mkU32(0xcccccccc)),
-                                            mkU8(0x2)),
-                                      binop(Iop_Shl32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t1),
-                                                  mkU32(0x33333333)),
-                                            mkU8(0x2))));
-                     assign(t3, binop(Iop_Or32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0xf0f0f0f0)),
-                                            mkU8(0x4)),
-                                      binop(Iop_Shl32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0x0f0f0f0f)),
-                                            mkU8(0x4))));
-                     assign(t4, binop(Iop_Or32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t3),
-                                                  mkU32(0xff00ff00)),
-                                            mkU8(0x8)),
-                                      binop(Iop_Shl32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t3),
-                                                  mkU32(0x00ff00ff)),
-                                            mkU8(0x8))));
-                     assign(t5, binop(Iop_Or32,
-                                      binop(Iop_Shr32,
-                                            mkexpr(t4),
-                                            mkU8(0x10)),
-                                      binop(Iop_Shl32,
-                                            mkexpr(t4),
-                                            mkU8(0x10))));
-                     putIReg(rd, binop(Iop_Shr32,
-                                       mkexpr(t5),
-                                       mkU8(16)));
-                     break;
-                  }
-                  case 0x1C: {  /* PRECEU.PH.QBL */
-                     DIP("preceu.ph.qbl r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0xff000000)),
-                                             mkU8(8)),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x00ff0000)),
-                                             mkU8(16))));
-                     break;
-                  }
-                  case 0x1E: {  /* PRECEU.PH.QBLA */
-                     DIP("preceu.ph.qbla r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0xff000000)),
-                                             mkU8(8)),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x0000ff00)),
-                                             mkU8(8))));
-                     break;
-                  }
-                  case 0x1D: {  /* PRECEU.PH.QBR */
-                     DIP("preceu.ph.qbr r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Shl32,
-                                             binop(Iop_And32,
-                                                   getIReg(rt),
-                                                   mkU32(0x0000ff00)),
-                                             mkU8(8)),
-                                       binop(Iop_And32,
-                                             getIReg(rt),
-                                             mkU32(0x000000ff))));
-                     break;
-                  }
-                  case 0x1F: {  /* PRECEU.PH.QBRA */
-                     DIP("preceu.ph.qbra r%u, r%u", rd, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_And32,
-                                             getIReg(rt),
-                                             mkU32(0x00ff0000)),
-                                       binop(Iop_And32,
-                                             getIReg(rt),
-                                             mkU32(0x000000ff))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of ABSQ_S.PH */
-            }
-            case 0x38: {  /* EXTR.W */
-               switch(sa) {
-                  case 0x0: {  /* EXTR.W */
-                     DIP("extr.w r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     if (0 == rs) {
-                        assign(t1, mkexpr(t0));
-                     } else {
-                        assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
-                     }
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least sifgnificant bit of the shifted value
-                        from acc. */
-                     if (0 == rs) {
-                        assign(t8, mkU64(0x0ULL));
-                     } else {
-                        assign(t8, binop(Iop_And64,
-                                         binop(Iop_Shr64,
-                                               mkexpr(t0),
-                                               mkU8(rs-1)),
-                                         mkU64(0x1ULL)));
-                     }
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+            case 0x02: { /* CLEI_U.W */
+               DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               tmp |= (tmp << 32);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT32Ux4,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ32x4,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+            case 0x03: { /* CLEI_U.D */
+               DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT64Ux2,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ64x2,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+         }
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     if (0 == rs) {
-                        putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
-                     } else {
-                        putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
-                     }
-                     break;
-                  }
-                  case 0x1: {  /* EXTRV.W */
-                     DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I8);
-
-                     assign(t15, unop(Iop_32to8,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0x1f))));
-                     assign(t0, getAcc(ac));
-                     assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        unop(Iop_8Uto32,
-                                                             mkexpr(t15)),
-                                                        mkU32(0)),
-                                                  unop(Iop_64to32, mkexpr(t0)),
-                                                  unop(Iop_64to32, mkexpr(t1))));
-
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least sifgnificant bit of the shifted value
-                        from acc. */
-                     assign(t8,
-                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                             unop(Iop_8Uto32,
-                                                  mkexpr(t15)),
-                                             mkU32(0)),
-                                       mkU64(0x0ULL),
-                                       binop(Iop_And64,
-                                             binop(Iop_Shr64,
-                                                   mkexpr(t0),
-                                                   unop(Iop_32to8,
-                                                        binop(Iop_Sub32,
-                                                              unop(Iop_8Uto32,
-                                                                   mkexpr(t15)),
-                                                                   mkU32(1)))),
-                                             mkU64(0x1ULL))));
-
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+         break;
+      }
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     break;
-                  }
-                  case 0x2: {  /* EXTP */
-                     DIP("extp r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     /* Extract pos field of DSPControl register. */
-                     assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
-                     /* Check if (pos - size) >= 0 [size <= pos]
-                        if (pos < size)
-                           put 1 to EFI field of DSPControl register
-                        else
-                           extract bits from acc and put 0 to EFI field of
-                           DSPCtrl */
-                     assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    binop(Iop_And32,
-                                                          getDSPControl(),
-                                                          mkU32(0xffffbfff)),
-                                                    mkU32(0x4000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xffffbfff))));
-
-                     /* If pos <= 31, shift right the value from the acc
-                        (pos-size) times and take (size+1) bits from the least
-                        significant positions. Otherwise, shift left the value
-                        (63-pos) times, take (size+1) bits from the most
-                        significant positions and shift right (31-size) times.*/
-                     assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
-                     assign(t4,
-                           IRExpr_ITE(mkexpr(t3),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkexpr(t1), mkU32(rs))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkU32(63), mkexpr(t1)))));
-
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Shr64,
-                                                 mkexpr(t0), mkexpr(t4)),
-                                           binop(Iop_Shl64,
-                                                 mkexpr(t0), mkexpr(t4))));
-
-                     /* t6 holds a mask for bit extraction */
-                     assign(t6,
-                            IRExpr_ITE(mkexpr(t3),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shl64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  mkU8(rs+1))),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shr64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  mkU8(rs+1)))));
-
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           unop(Iop_64to32,
-                                                binop(Iop_And64,
-                                                      mkexpr(t5),
-                                                      mkexpr(t6))),
-                                           binop(Iop_Shr32,
-                                                 unop(Iop_64HIto32,
-                                                      binop(Iop_And64,
-                                                            mkexpr(t5),
-                                                            mkexpr(t6))),
-                                                 mkU8(31-rs))));
+      case 0x06: { /* LDI.df */
+         ULong tmp;
+         UShort s10;
+         s10 = (cins & 0x001FF800) >> 11;
 
-                     putIReg(rt, mkexpr(t7));
-                     break;
-                  }
-                  case 0x3: {  /* EXTPV */
-                     DIP("extpv r%u, ac%u, r%u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
-                     assign(t0, getAcc(ac));
-                     /* Extract pos field of DSPControl register. */
-                     assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
-                     /* Check if (pos - size) >= 0 [size <= pos]
-                        if (pos < size)
-                           put 1 to EFI field of DSPControl register
-                        else
-                           extract bits from acc and put 0 to EFI field of
-                           DSPCtrl */
-                     assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    binop(Iop_And32,
-                                                          getDSPControl(),
-                                                          mkU32(0xffffbfff)),
-                                                    mkU32(0x4000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xffffbfff))));
-
-                     /* If pos <= 31, shift right the value from the acc
-                        (pos-size) times and take (size+1) bits from the least
-                        significant positions. Otherwise, shift left the value
-                        (63-pos) times, take (size+1) bits from the most
-                        significant positions and shift right (31-size)
-                        times. */
-                     assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
-                     assign(t4,
-                           IRExpr_ITE(mkexpr(t3),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkexpr(t1), mkexpr(t8))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkU32(63), mkexpr(t1)))));
-
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Shr64,
-                                                 mkexpr(t0), mkexpr(t4)),
-                                           binop(Iop_Shl64,
-                                                 mkexpr(t0), mkexpr(t4))));
-
-                     /* t6 holds a mask for bit extraction. */
-                     assign(t6,
-                            IRExpr_ITE(mkexpr(t3),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shl64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Add32,
-                                                             mkexpr(t8),
-                                                             mkU32(1))))),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shr64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Add32,
-                                                             mkexpr(t8),
-                                                             mkU32(1)))))));
-
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           unop(Iop_64to32,
-                                                binop(Iop_And64,
-                                                      mkexpr(t5),
-                                                      mkexpr(t6))),
-                                           binop(Iop_Shr32,
-                                                 unop(Iop_64HIto32,
-                                                      binop(Iop_And64,
-                                                            mkexpr(t5),
-                                                            mkexpr(t6))),
-                                                 unop(Iop_32to8,
-                                                      binop(Iop_Sub32,
-                                                            mkU32(31),
-                                                            mkexpr(t8))))));
+         switch (df) {
+            case 0x00: /* LDI.B */
+               DIP("LDI.B w%d, %d", wd, s10);
+               tmp = s10 & 0xFFl;
+               tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
+                     | (tmp << 32) | (tmp << 40) | (tmp << 48) |
+                     (tmp << 56);
+               break;
 
-                     putIReg(rt, mkexpr(t7));
-                     break;
-                  }
-                  case 0x4: {  /* EXTR_R.W */
-                     DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I64);
-                     t16 = newTemp(Ity_I1);
-
-                     assign(t0, getAcc(ac));
-                     assign(t16, binop(Iop_CmpEQ32,
-                                       mkU32(rs),
-                                       mkU32(0)));
-                     assign(t1, IRExpr_ITE(mkexpr(t16),
-                                           mkexpr(t0),
-                                           binop(Iop_Sar64,
-                                                 mkexpr(t0),
-                                                 mkU8(rs))));
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least significant bit of the shifted value
-                        from acc. */
-                     assign(t15, binop(Iop_Shr64,
-                                       mkexpr(t0),
-                                       unop(Iop_32to8,
-                                            binop(Iop_Sub32,
-                                                  binop(Iop_And32,
-                                                        mkU32(rs),
-                                                        mkU32(0x1f)),
-                                                  mkU32(1)))));
-
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t16),
-                                       mkU64(0x0ULL),
-                                       binop(Iop_And64,
-                                             mkexpr(t15),
-                                             mkU64(0x0000000000000001ULL))));
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-                     putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
-
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+            case 0x01: /* LDI.H */
+               DIP("LDI.H w%d, %d", wd, s10);
+               tmp = extend_s_10to16(s10);
+               tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
+               break;
 
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+            case 0x02: /* LDI.W */
+               DIP("LDI.W w%d, %d", wd, s10);
+               tmp = extend_s_10to32(s10);
+               tmp = tmp | (tmp << 32);
+               break;
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     break;
-                  }
-                  case 0x5: {  /* EXTRV_R.W */
-                     DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I8);
-
-                     assign(t15, unop(Iop_32to8,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0x1f))));
-                     assign(t0, getAcc(ac));
-                     assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
-
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least sifgnificant bit of the shifted value
-                        from acc. */
-                     assign(t8,
-                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                             unop(Iop_8Uto32,
-                                                  mkexpr(t15)),
-                                             mkU32(0)),
-                                       mkU64(0x0ULL),
-                                       binop(Iop_And64,
-                                             binop(Iop_Shr64,
-                                                   mkexpr(t0),
-                                                   unop(Iop_32to8,
-                                                        binop(Iop_Sub32,
-                                                              unop(Iop_8Uto32,
-                                                                   mkexpr(t15)),
-                                                                   mkU32(1)))),
-                                             mkU64(0x1ULL))));
-
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-                     /* Put rounded value in destination register. */
-                     putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
-
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+            case 0x03: /* LDI.D */
+               DIP("LDI.D w%d, %d", wd, s10);
+               tmp = extend_s_10to64(s10);
+               break;
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     break;
-                  }
-                  case 0x6: {  /* EXTR_RS.W */
-                     DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t16 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     if (0 == rs) {
-                        assign(t1, mkexpr(t0));
-                     } else {
-                        assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
-                     }
+            default:
+               return -1;
+         }
 
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least sifgnificant bit of the shifted value
-                        from acc. */
-                     if (0 == rs) {
-                        assign(t8, mkU64(0x0ULL));
-                     } else {
-                        assign(t8, binop(Iop_And64,
-                                         binop(Iop_Shr64,
-                                               mkexpr(t0),
-                                               mkU8(rs-1)),
-                                         mkU64(0x1ULL)));
-                     }
+         putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+         break;
+      }
 
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+      default:
+         return -1;
+   }
 
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+   return 0;
+}
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     assign(t16, binop(Iop_And32,
-                                       unop(Iop_64HIto32,
-                                            mkexpr(t9)),
-                                       mkU32(0x80000000)));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t14),
-                                                  mkU32(0)),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             mkexpr(t16),
-                                                             mkU32(0)),
-                                                       mkU32(0x7fffffff),
-                                                       mkU32(0x80000000)),
-                                            unop(Iop_64to32, mkexpr(t9))));
-                     break;
-                  }
-                  case 0x7: {  /* EXTRV_RS.W */
-                     DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I32);
-                     t16 = newTemp(Ity_I32);
-                     t17 = newTemp(Ity_I1);
-
-                     assign(t15, binop(Iop_And32,
-                                       getIReg(rs),
-                                       mkU32(0x1f)));
-                     assign(t17, binop(Iop_CmpEQ32,
-                                       mkexpr(t15),
-                                       mkU32(0)));
-                     assign(t0, getAcc(ac));
-                     assign(t1, IRExpr_ITE(mkexpr(t17),
-                                           mkexpr(t0),
-                                           binop(Iop_Sar64,
-                                                 mkexpr(t0),
-                                                 unop(Iop_32to8,
-                                                      mkexpr(t15)))));
-
-                     /* Check if bits 63..31 of the result in t1 aren't 0. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
-                     /* Check if bits 63..31 of the result in t1 aren't
-                        0x1ffffffff. */
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t1)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-                     /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
-                        control register. */
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t3)),
-                                            unop(Iop_1Sto32, mkexpr(t4))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t5)),
-                                            unop(Iop_1Sto32, mkexpr(t6)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t7),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     /* If the last discarded bit is 1, there would be carry
-                        when rounding, otherwise there wouldn't. We use that
-                        fact and just add the value of the last discarded bit
-                        to the least sifgnificant bit of the shifted value
-                        from acc. */
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t17),
-                                       mkU64(0x0ULL),
-                                       binop(Iop_And64,
-                                             binop(Iop_Shr64,
-                                                   mkexpr(t0),
-                                                   unop(Iop_32to8,
-                                                        binop(Iop_Sub32,
-                                                              mkexpr(t15),
-                                                              mkU32(1)))),
-                                             mkU64(0x1ULL))));
-
-                     assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-
-                     /* Repeat previous steps for the rounded value. */
-                     assign(t10, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0)));
-                     assign(t11, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0)));
+static Int msa_BIT_09(UInt cins, UChar wd, UChar ws)   /* BIT (0x09) */
+{
+   IRTemp t1, t2, t3;
+   UShort operation;
+   UChar df, m;
 
-                     assign(t12, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32,
-                                           mkexpr(t9)),
-                                      mkU32(0xffffffff)));
-                     assign(t13, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t9)),
-                                            mkU32(0x80000000)),
-                                      mkU32(0x80000000)));
-
-                     assign(t14, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t10)),
-                                            unop(Iop_1Sto32, mkexpr(t11))),
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32, mkexpr(t12)),
-                                            unop(Iop_1Sto32, mkexpr(t13)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t14),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-
-                     assign(t16, binop(Iop_And32,
-                                       unop(Iop_64HIto32,
-                                            mkexpr(t9)),
-                                       mkU32(0x80000000)));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t14),
-                                                  mkU32(0)),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             mkexpr(t16),
-                                                             mkU32(0)),
-                                                       mkU32(0x7fffffff),
-                                                       mkU32(0x80000000)),
-                                            unop(Iop_64to32, mkexpr(t9))));
-                     break;
-                  }
-                  case 0xA: {  /* EXTPDP */
-                     DIP("extpdp r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     /* Extract pos field of DSPControl register. */
-                     assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
-                     /* Check if (pos - size) >= 0 [size <= pos]
-                        if (pos < size)
-                           put 1 to EFI field of DSPControl register
-                        else
-                           extract bits from acc and put 0 to EFI field of
-                           DSPCtrl */
-                     assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
-
-                     assign(t8, binop(Iop_Or32,
-                                      binop(Iop_And32,
-                                            getDSPControl(),
-                                            mkU32(0xffffbfc0)),
-                                      binop(Iop_And32,
-                                            binop(Iop_Sub32,
-                                                  binop(Iop_And32,
-                                                        getDSPControl(),
-                                                        mkU32(0x3f)),
-                                                  mkU32(rs+1)),
-                                            mkU32(0x3f))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                     binop(Iop_And32,
-                                                           getDSPControl(),
-                                                           mkU32(0xffffbfff)),
-                                                     mkU32(0x4000)),
-                                              mkexpr(t8)));
-
-                     /* If pos <= 31, shift right the value from the acc
-                        (pos-size) times and take (size+1) bits from the least
-                        significant positions. Otherwise, shift left the value
-                        (63-pos) times, take (size+1) bits from the most
-                        significant positions and shift right (31-size) times.
-                     */
-                     assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t3),
-                                       unop(Iop_32to8,
-                                            binop(Iop_Sub32,
-                                                  mkexpr(t1), mkU32(rs))),
-                                       unop(Iop_32to8,
-                                            binop(Iop_Sub32,
-                                                  mkU32(63), mkexpr(t1)))));
-
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Shr64,
-                                                 mkexpr(t0), mkexpr(t4)),
-                                           binop(Iop_Shl64,
-                                                 mkexpr(t0), mkexpr(t4))));
-
-                     /* t6 holds a mask for bit extraction. */
-                     assign(t6,
-                            IRExpr_ITE(mkexpr(t3),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shl64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  mkU8(rs+1))),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shr64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  mkU8(rs+1)))));
-
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           unop(Iop_64to32,
-                                                binop(Iop_And64,
-                                                      mkexpr(t5),
-                                                      mkexpr(t6))),
-                                           binop(Iop_Shr32,
-                                                 unop(Iop_64HIto32,
-                                                      binop(Iop_And64,
-                                                            mkexpr(t5),
-                                                            mkexpr(t6))),
-                                                 mkU8(31-rs))));
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x007F0000) >> 16;
 
-                     putIReg(rt, mkexpr(t7));
-                     break;
-                  }
-                  case 0xB: {  /* EXTPDPV */
-                     DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-
-                     assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
-                     assign(t0, getAcc(ac));
-                     /* Extract pos field of DSPControl register. */
-                     assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
-                     /* Check if (pos - size) >= 0 [size <= pos]
-                        if (pos < size)
-                           put 1 to EFI field of DSPControl register
-                        else
-                           extract bits from acc and put 0 to EFI field of
-                           DSPCtrl */
-                     assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
-
-                     assign(t9, binop(Iop_Or32,
-                                      binop(Iop_And32,
-                                            getDSPControl(),
-                                            mkU32(0xffffbfc0)),
-                                      binop(Iop_And32,
-                                            binop(Iop_Sub32,
-                                                  binop(Iop_And32,
-                                                        getDSPControl(),
-                                                        mkU32(0x3f)),
-                                                  binop(Iop_Add32,
-                                                        mkexpr(t8),
-                                                        mkU32(0x1))),
-                                            mkU32(0x3f))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    binop(Iop_And32,
-                                                          getDSPControl(),
-                                                          mkU32(0xffffbfff)),
-                                                    mkU32(0x4000)),
-                                              mkexpr(t9)));
-
-                     /* If pos <= 31, shift right the value from the acc
-                        (pos-size) times and take (size+1) bits from the least
-                        significant positions. Otherwise, shift left the value
-                        (63-pos) times, take (size+1) bits from the most
-                        significant positions and shift right (31-size) times.
-                     */
-                     assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t3),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkexpr(t1), mkexpr(t8))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 mkU32(63), mkexpr(t1)))));
-
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Shr64,
-                                                 mkexpr(t0), mkexpr(t4)),
-                                           binop(Iop_Shl64,
-                                                 mkexpr(t0), mkexpr(t4))));
-
-                     /* t6 holds a mask for bit extraction. */
-                     assign(t6,
-                            IRExpr_ITE(mkexpr(t3),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shl64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Add32,
-                                                             mkexpr(t8),
-                                                             mkU32(1))))),
-                                       unop(Iop_Not64,
-                                            binop(Iop_Shr64,
-                                                  mkU64(0xffffffffffffffffULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Add32,
-                                                             mkexpr(t8),
-                                                             mkU32(1)))))));
-
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           unop(Iop_64to32,
-                                                binop(Iop_And64,
-                                                      mkexpr(t5),
-                                                      mkexpr(t6))),
-                                           binop(Iop_Shr32,
-                                                 unop(Iop_64HIto32,
-                                                      binop(Iop_And64,
-                                                            mkexpr(t5),
-                                                            mkexpr(t6))),
-                                                 unop(Iop_32to8,
-                                                      binop(Iop_Sub32,
-                                                            mkU32(31),
-                                                            mkexpr(t8))))));
+   if ((df & 0x70) == 0x70) {        // 111mmmm; b
+      m = df & 0x07;
+      df = 0;
+   } else if ((df & 0x60) == 0x60) { // 110mmmm; h
+      m = df & 0x0F;
+      df = 1;
+   } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
+      m = df & 0x1F;
+      df = 2;
+   } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
+      m = df & 0x3F;
+      df = 3;
+   }
 
-                     putIReg(rt, mkexpr(t7));
-                     break;
-                  }
-                  case 0xE: {  /* EXTR_S.H */
-                     DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
+   switch (operation) {
+      case 0x00: { /* SLLI.df */
+         switch (df) {
+            case 0x00: { /* SLLI.B */
+               DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t0, getAcc(ac));
+            case 0x01: { /* SLLI.H */
+               DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+            case 0x02: { /* SLLI.W */
+               DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t2, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
+            case 0x03: { /* SLLI.D */
+               DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
+               break;
+            }
+         }
 
-                     assign(t9, binop(Iop_And32,
-                                      unop(Iop_64to32,
-                                           mkexpr(t1)),
-                                      mkU32(0x80000000)));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t9),
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               mkexpr(t0)),
-                                                          mkU32(0x80000000))),
-                                              mkexpr(t2),
-                                              getDSPControl()));
+         break;
+      }
 
-                     /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
-                        1. subtract 0x7fff from t1
-                        2. if the resulting number is positive (sign bit = 0)
-                           and any of the other bits is 1, the value is > 0. */
-                     assign(t3, binop(Iop_Sub64,
-                                      mkexpr(t1),
-                                      mkU64(0x0000000000007fffULL)));
-                     assign(t4, binop(Iop_And32,
-                                       binop(Iop_Or32,
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       binop(Iop_And32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t3)),
-                                                             mkU32(0x7fffffff)))),
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t3))))),
-                                       unop(Iop_1Sto32,
-                                            binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        unop(Iop_64HIto32,
-                                                                  mkexpr(t3)),
-                                                             mkU32(0x80000000)),
-                                                  mkU32(0)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t4)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
-                        1. subtract t1 from 0xffffffffffff8000
-                        2. if the resulting number is positive (sign bit = 0)
-                            and any of the other bits is 1, the value is > 0 */
-                     assign(t6, binop(Iop_Sub64,
-                                       mkU64(0xffffffffffff8000ULL),
-                                       mkexpr(t1)));
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       binop(Iop_And32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t6)),
-                                                             mkU32(0x7fffffff)))),
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t6))))),
-                                      unop(Iop_1Sto32,
-                                            binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        unop(Iop_64HIto32,
-                                                                  mkexpr(t6)),
-                                                             mkU32(0x80000000)),
-                                                  mkU32(0)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t7)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t4)),
-                                            mkU32(0x00007fff),
-                                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                                             mkU32(0),
-                                                             mkexpr(t7)),
-                                                       mkU32(0xffff8000),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t1)))));
-                     break;
-                  }
-                  case 0xF: {  /* EXTRV_S.H */
-                     DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
+      case 0x01: { /* SRAI.df */
+         switch (df) {
+            case 0x00: { /* SRAI.B */
+               DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t0, getAcc(ac));
+            case 0x01: { /* SRAI.H */
+               DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t1, binop(Iop_Sar64,
-                                      mkexpr(t0),
-                                      unop(Iop_32to8,
-                                           binop(Iop_And32,
-                                                 getIReg(rs),
-                                                 mkU32(0x1f)))));
+            case 0x02: { /* SRAI.W */
+               DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     assign(t2, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
+            case 0x03: { /* SRAI.D */
+               DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
+               break;
+            }
+         }
 
-                     assign(t9, binop(Iop_And32,
-                                      unop(Iop_64to32,
-                                           mkexpr(t1)),
-                                      mkU32(0x80000000)));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t9),
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               mkexpr(t0)),
-                                                          mkU32(0x80000000))),
-                                              mkexpr(t2),
-                                              getDSPControl()));
+         break;
+      }
 
-                     /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
-                        1. subtract 0x7fff from t1
-                        2. if the resulting number is positive (sign bit = 0)
-                           and any of the other bits is 1, the value is > 0. */
-                     assign(t3, binop(Iop_Sub64,
-                                      mkexpr(t1),
-                                      mkU64(0x0000000000007fffULL)));
-                     assign(t4, binop(Iop_And32,
-                                       binop(Iop_Or32,
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       binop(Iop_And32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t3)),
-                                                             mkU32(0x7fffffff)))),
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t3))))),
-                                       unop(Iop_1Sto32,
-                                            binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        unop(Iop_64HIto32,
-                                                                  mkexpr(t3)),
-                                                             mkU32(0x80000000)),
-                                                  mkU32(0)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t4)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
-                        1. subtract t1 from 0xffffffffffff8000
-                        2. if the resulting number is positive (sign bit = 0)
-                            and any of the other bits is 1, the value is > 0 */
-                     assign(t6, binop(Iop_Sub64,
-                                       mkU64(0xffffffffffff8000ULL),
-                                       mkexpr(t1)));
-                     assign(t7, binop(Iop_And32,
-                                      binop(Iop_Or32,
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       binop(Iop_And32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t6)),
-                                                             mkU32(0x7fffffff)))),
-                                            unop(Iop_1Sto32,
-                                                 binop(Iop_CmpNE32,
-                                                       mkU32(0),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t6))))),
-                                      unop(Iop_1Sto32,
-                                            binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        unop(Iop_64HIto32,
-                                                                  mkexpr(t6)),
-                                                             mkU32(0x80000000)),
-                                                  mkU32(0)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t7)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00800000)),
-                                              getDSPControl()));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkU32(0),
-                                                    mkexpr(t4)),
-                                            mkU32(0x00007fff),
-                                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                                             mkU32(0),
-                                                             mkexpr(t7)),
-                                                       mkU32(0xffff8000),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t1)))));
-                     break;
-                  }
-                  case 0x12: {  /* RDDSP*/
-                     DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask);
-                     vassert(!mode64);
+      case 0x02: { /* SRLI.df */
+         switch (df) {
+            case 0x00: { /* SRLI.B */
+               DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     putIReg(rd, mkU32(0x0));
+            case 0x01: { /* SRLI.H */
+               DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     if ((rddsp_mask & 0x1) == 0x1) {
-                        /* Read pos field (bits 5-0) of DSPControl register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0x0000003F))));
-                     }
+            case 0x02: { /* SRLI.W */
+               DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
+               break;
+            }
 
-                     if ((rddsp_mask & 0x2) == 0x2) {
-                        /* Read scount field (bits 12-7) of DSPControl
-                           register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0x00001F80))));
-                     }
+            case 0x03: { /* SRLI.D */
+               DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
+               putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
+               break;
+            }
+         }
 
-                     if ((rddsp_mask & 0x4) == 0x4) {
-                        /* Read C field (bit 13) of DSPControl register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0x00002000))));
-                     }
+         break;
+      }
 
-                     if ((rddsp_mask & 0x8) == 0x8) {
-                        /* Read outflag field (bit s 23-16) of DSPControl
-                           register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0x00FF0000))));
-                     }
+      case 0x03: { /* BCLRI.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
 
-                     if ((rddsp_mask & 0x10) == 0x10) {
-                        /* Read ccond field (bits 31-24) of DSPControl
-                           register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0xFF000000))));
-                     }
+         switch (df) {
+            case 0x00: { /* BCLRI.B */
+               DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2, binop(Iop_ShlN8x16,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     if ((rddsp_mask & 0x20) == 0x20) {
-                        /* Read EFI field (bit 14) of DSPControl register. */
-                        putIReg(rd, binop(Iop_Or32,
-                                          getIReg(rd),
-                                          binop(Iop_And32,
-                                                getDSPControl(),
-                                                mkU32(0x00004000))));
-                     }
+            case 0x01: { /* BCLRI.H */
+               DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2, binop(Iop_ShlN16x8,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     if ((rddsp_mask & 0x3f) == 0x3f) {
-                        /* Read all fields of DSPControl register. */
-                        putIReg(rd, getDSPControl());
-                     }
-                     break;
-                  }
-                  case 0x13: {  /* WRDSP */
-                     DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask);
-                     vassert(!mode64);
-
-                     if ((wrdsp_mask & 0x3f) == 0x3f) {
-                        /* If mips64 put all fields of rs, except bit 15 and bit
-                           6, to DSPControl register, otherwise put all except
-                           bits 15, 6 and bits 31..28. */
-                        putDSPControl(mode64 ?
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0xffff7fbf)) :
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0x0fff7fbf)));
-                     } else {
-                        if ((wrdsp_mask & 0x1) == 0x1) {
-                           /* Put bits 5-0 of rs to DSPControl register pos
-                              field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0xFFFF7F40)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mkU32(0x0000003F))));
-                        }
+            case 0x02: { /* BCLRI.W */
+               DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 32);
+               assign(t2, binop(Iop_ShlN32x4,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                        if ((wrdsp_mask & 0x2) == 0x2) {
-                           /* Put bits 12-7 of rs to DSPControl scount field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0xFFFFE03F)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mkU32(0x00001F80))));
-                        }
+            case 0x03: { /* BCLRI.D */
+               DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
+               assign(t2, binop(Iop_ShlN64x2,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
+         }
 
-                        if ((wrdsp_mask & 0x4) == 0x4) {
-                           /* Put bit 13 of rs to DSPControl register C
-                              field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0xFFFF5FBF)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mkU32(0x00002000))));
-                        }
+         assign(t3, binop(Iop_AndV128,
+                          mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-                        if ((wrdsp_mask & 0x8) == 0x8) {
-                           /* Put bits 23-16 of rs to DSPControl reg outflag
-                              field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0xFF007FBF)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mkU32(0x00FF0000))));
-                        }
+      case 0x04: { /* BSETI */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
 
-                        if ((wrdsp_mask & 0x10) == 0x10) {
-                           /* Put bits 31-24 of rs to DSPControl reg ccond
-                              field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0x00FF7FBF)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mode64 ? mkU32(0xFF000000)
-                                                            : mkU32(0x0F000000))
-                                               )
-                                        );
-                        }
+         switch (df) {
+            case 0x00: { /* BSETI.B */
+               DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2, binop(Iop_ShlN8x16,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                        if ((wrdsp_mask & 0x20) == 0x20) {
-                           /* Put bit 14 of rs to DSPControl register EFI
-                              field. */
-                           putDSPControl(binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     getDSPControl(),
-                                                     mkU32(0xFFFF3FBF)),
-                                               binop(Iop_And32,
-                                                     getIReg(rs),
-                                                     mkU32(0x00004000))));
-                        }
-                     }
-                     break;
-                  }
-                  case 0x1A: {  /* SHILO */
-                     DIP("shilo ac%u, %u", ac, shift);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
+            case 0x01: { /* BSETI.H */
+               DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2, binop(Iop_ShlN16x8,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     assign(t0, getAcc(ac));
+            case 0x02: { /* BSETI.W */
+               DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 32);
+               assign(t2, binop(Iop_ShlN32x4,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     putAcc(ac, mkexpr(t0));
+            case 0x03: { /* BSETI.D */
+               DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
+               assign(t2, binop(Iop_ShlN64x2,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
+         }
 
-                     if (0x20 == (shift & 0x3f)) {
-                        putAcc(ac, binop(Iop_32HLto64,
-                                         unop(Iop_64to32, mkexpr(t0)),
-                                         mkU32(0x0)));
-                     } else if (0x20 == (shift & 0x20)) {
-                        assign(t1, binop(Iop_Shl64,
-                                         mkexpr(t0),
-                                         unop(Iop_32to8,
-                                              binop(Iop_Add32,
-                                                    unop(Iop_Not32,
-                                                         mkU32(shift)),
-                                                    mkU32(0x1)))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-                        putAcc(ac, mkexpr(t1));
-                     } else {
-                        assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
+      case 0x05: { /* BNEGI.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
 
-                        putAcc(ac, mkexpr(t1));
-                     }
-                     break;
-                  }
-                  case 0x1B: {  /* SHILOV */
-                     DIP("shilov ac%u, r%u", ac, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-                     assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
-                     assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
-                     assign(t3, binop(Iop_Shl64,
-                                      mkexpr(t0),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Add32,
-                                                 unop(Iop_Not32,
-                                                      mkexpr(t1)),
-                                                 mkU32(0x1)))));
-                     assign(t4, binop(Iop_Shr64,
-                                      mkexpr(t0),
-                                      unop(Iop_32to8,
-                                           mkexpr(t1))));
-
-                     putAcc(ac,
-                            IRExpr_ITE(mkexpr(t2),
-                                       binop(Iop_32HLto64,
-                                             unop(Iop_64to32, mkexpr(t0)),
-                                             mkU32(0x0)),
-                                       IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        binop(Iop_And32,
-                                                              mkexpr(t1),
-                                                              mkU32(0x20)),
-                                                        mkU32(0x20)),
-                                                  mkexpr(t3),
-                                                  mkexpr(t4))));
-                     break;
-                  }
-                  case 0x1F: {  /* MTHLIP */
-                     DIP("mthlip r%u, ac%u", rs, ac);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-
-                     assign(t0, getAcc(ac));
-                     putAcc(ac, binop(Iop_32HLto64,
-                                      unop(Iop_64to32, mkexpr(t0)),
-                                      getIReg(rs)));
-                     assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
-                                                    mkU32(32),
-                                                    mkexpr(t1)),
-                                              binop(Iop_Or32,
-                                                    binop(Iop_Sub32,
-                                                          mkexpr(t1),
-                                                          mkU32(32)),
-                                                   binop(Iop_And32,
-                                                         getDSPControl(),
-                                                         mkU32(0xffffffc0))),
-                                              binop(Iop_Or32,
-                                                    binop(Iop_Add32,
-                                                          mkexpr(t1),
-                                                          mkU32(32)),
-                                                    binop(Iop_And32,
-                                                          getDSPControl(),
-                                                          mkU32(0xffffffc0)))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of EXTR.W */
+         switch (df) {
+            case 0x00: { /* BNEGI.B */
+               DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2, binop(Iop_ShlN8x16,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
             }
-            case 0xA: {  /* LX */
-               switch(sa) {
-                  case 0x0: {  /* LWX */
-                     DIP("lwx r%u, r%u(r%u)", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
 
-                     assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+            case 0x01: { /* BNEGI.H */
+               DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2, binop(Iop_ShlN16x8,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     putIReg(rd, load(Ity_I32, mkexpr(t0)));
-                     break;
-                  }
-                  case 0x4: {  /* LHX */
-                     DIP("lhx r%u, r%u(r%u)", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
+            case 0x02: { /* BNEGI.W */
+               DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
+               tmp |= (tmp << 32);
+               assign(t2, binop(Iop_ShlN32x4,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
 
-                     assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+            case 0x03: { /* BNEGI.D */
+               DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
+               assign(t2, binop(Iop_ShlN64x2,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               break;
+            }
+         }
 
-                     putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x6: {  /* LBUX */
-                     DIP("lbux r%u, r%u(r%u)", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-                     assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+      case 0x06: { /* BINSLI.df */
+         switch (df) {
+            case 0x00: { /* BINSLI.B */
+               DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8080808080808080ULL;
+               assign(t1, binop(Iop_SarN8x16,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of LX */
-            }
-            case 0xC: {  /* INSV */
-               switch(sa) {
-                  case 0x0: {  /* INSV */
-                     DIP("insv r%u, r%u", rt, rs);
-                     vassert(!mode64);
-
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-
-                     /* t0 <- pos field of DSPControl register. */
-                     assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-                     /* t1 <- scount field of DSPControl register. */
-                     assign(t1, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            getDSPControl(),
-                                            mkU32(0x1f80)),
-                                      mkU8(7)));
-
-                     assign(t2, unop(Iop_32to8,
-                                     binop(Iop_Add32,
-                                           mkexpr(t1),
-                                           mkexpr(t0))));
+            case 0x01: { /* BINSLI.H */
+               DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000800080008000ULL;
+               assign(t1,
+                      binop(Iop_SarN16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     /* 32-(pos+size) most significant bits of rt. */
-                     assign(t6, binop(Iop_Shl32,
-                                      binop(Iop_Shr32,
-                                            getIReg(rt),
-                                            mkexpr(t2)),
-                                      mkexpr(t2)));
+            case 0x02: { /* BINSLI.W */
+               DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000000080000000ULL;
+               assign(t1,
+                      binop(Iop_SarN32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     assign(t3, unop(Iop_32to8,
-                                     binop(Iop_Sub32,
-                                           mkU32(32),
-                                           mkexpr(t0))));
-                     /* Pos least significant bits of rt. */
-                     assign(t7, binop(Iop_Shr32,
-                                      binop(Iop_Shl32,
-                                            getIReg(rt),
-                                            mkexpr(t3)),
-                                      mkexpr(t3)));
-
-                     /* Size least significant bits of rs,
-                        shifted to appropriate position. */
-                     assign(t8, binop(Iop_Shl32,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            unop(Iop_Not32,
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0xffffffff),
-                                                       unop(Iop_32to8,
-                                                            mkexpr(t1))))),
-                                      unop(Iop_32to8,
-                                           mkexpr(t0))));
-
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  mkexpr(t0),
-                                                  mkU32(0)),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             mkexpr(t1),
-                                                             mkU32(32)),
-                                                       getIReg(rs),
-                                                       binop(Iop_Or32,
-                                                             mkexpr(t6),
-                                                             mkexpr(t8))),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             unop(Iop_8Uto32,
-                                                                  mkexpr(t2)),
-                                                             mkU32(32)),
-                                                       binop(Iop_Or32,
-                                                             mkexpr(t7),
-                                                             mkexpr(t8)),
-                                                       binop(Iop_Or32,
-                                                             binop(Iop_Or32,
-                                                                   mkexpr(t6),
-                                                                   mkexpr(t7)),
-                                                             mkexpr(t8)))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* enf of INSV */
-            }
-            case 0x10: {  /* ADDU.QB */
-               switch(sa) {
-                  case 0x00: {  /* ADDU.QB */
-                     DIP("addu.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I32);
-
-                     /* Add rightmost bytes of rs and rt. */
-                     assign(t0,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t1 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t2,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t3 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t2),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
+            case 0x03: { /* BINSLI.D */
+               DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000000000000000ULL;
+               assign(t1,
+                      binop(Iop_SarN64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t4,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t5 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t4),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t6,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t7 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t6),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     assign(t8,
-                            binop(Iop_Or32,
-                                  binop(Iop_Or32,
-                                        binop(Iop_Or32,
-                                              unop(Iop_1Sto32, mkexpr(t7)),
-                                              unop(Iop_1Sto32,  mkexpr(t5))),
-                                        unop(Iop_1Sto32, mkexpr(t3))),
-                                  unop(Iop_1Sto32, mkexpr(t1))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    mkexpr(t8),
-                                                    mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       binop(Iop_8HLto16,
-                                             unop(Iop_32to8, mkexpr(t6)),
-                                             unop(Iop_32to8, mkexpr(t4))),
-                                       binop(Iop_8HLto16,
-                                             unop(Iop_32to8, mkexpr(t2)),
-                                             unop(Iop_32to8, mkexpr(t0)))));
-                     break;
-                  }
-                  case 0x1: {  /* SUBU.QB */
-                     DIP("subu.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I32);
-
-                     /* Subtract rightmost bytes of rs and rt. */
-                     assign(t0,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t1 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     /* Subtract bits 15-8 of rs and rt. */
-                     assign(t2,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t3 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t2),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     /* Subtract bits 15-8 of rs and rt. */
-                     assign(t4,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t5 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t4),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     /* Subtract bits 15-8 of rs and rt. */
-                     assign(t6,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t7 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t6),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-
-                     assign(t8, binop(Iop_Or32,
-                                      binop(Iop_Or32,
-                                            binop(Iop_Or32,
-                                                  unop(Iop_1Sto32, mkexpr(t7)),
-                                                  unop(Iop_1Sto32, mkexpr(t5))),
-                                            unop(Iop_1Sto32, mkexpr(t3))),
-                                      unop(Iop_1Sto32, mkexpr(t1))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                     mkexpr(t8),
-                                                     mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       binop(Iop_8HLto16,
-                                             unop(Iop_32to8, mkexpr(t6)),
-                                             unop(Iop_32to8, mkexpr(t4))),
-                                       binop(Iop_8HLto16,
-                                             unop(Iop_32to8, mkexpr(t2)),
-                                             unop(Iop_32to8, mkexpr(t0)))));
-                     break;
-                  }
-                  case 0x04: {  /* ADDU_S.QB */
-                     DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I8);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I8);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I8);
-                     t12 = newTemp(Ity_I32);
-
-                     /* Add rightmost bytes of rs and rt. */
-                     assign(t0,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t1 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     /* Saturate if necessary. */
-                     assign(t2, IRExpr_ITE(mkexpr(t1),
-                                           mkU8(0xff),
-                                           unop(Iop_32to8, mkexpr(t0))));
-
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t3,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* t4 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t4, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t3),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     /* Saturate if necessary. */
-                     assign(t5, IRExpr_ITE(mkexpr(t4),
-                                           mkU8(0xff),
-                                           unop(Iop_32to8, mkexpr(t3))));
-
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t6,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t7 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t6),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     /* Saturate if necessary. */
-                     assign(t8, IRExpr_ITE(mkexpr(t7),
-                                           mkU8(0xff),
-                                           unop(Iop_32to8, mkexpr(t6))));
-
-                     /* Add bits 15-8 of rs and rt. */
-                     assign(t9,
-                            binop(Iop_Add32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     /* t10 will be 1 if there is overflow, 0 otherwise. */
-                     assign(t10, binop(Iop_CmpEQ32,
-                                       binop(Iop_And32,
-                                             mkexpr(t9),
-                                             mkU32(0x00000100)),
-                                       mkU32(0x00000100)));
-                     /* Saturate if necessary. */
-                     assign(t11, IRExpr_ITE(mkexpr(t10),
-                                            mkU8(0xff),
-                                            unop(Iop_32to8, mkexpr(t9))));
-
-                     assign(t12,
-                            binop(Iop_Or32,
-                                  binop(Iop_Or32,
-                                        binop(Iop_Or32,
-                                              unop(Iop_1Sto32, mkexpr(t10)),
-                                              unop(Iop_1Sto32, mkexpr(t7))),
-                                        unop(Iop_1Sto32, mkexpr(t4))),
-                                  unop(Iop_1Sto32, mkexpr(t1))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    mkexpr(t12),
-                                                    mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000))));
-
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
-                                   binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
-                     break;
-                  }
-                  case 0x05: {  /* SUBU_S.QB */
-                     DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-
-                     /* Use C function to easily calculate the result
-                        and write it in the register more conveniently
-                        Underflow is checked using step by step subtraction. */
-                     assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
-
-                     /* Subtract each byte of rs and rt. */
-                     assign(t6,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t7,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t8,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t9,
-                            binop(Iop_Sub32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-
-                     /* Put 1 to bit 20 in DSPControl if there is underflow
-                        in either byte. */
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t6),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t7),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     assign(t4, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t8),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            mkexpr(t9),
-                                            mkU32(0x00000100)),
-                                      mkU32(0x00000100)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t5),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     putIReg(rd, mkexpr(t1));
-                     break;
-                  }
-                  case 0x6: {  /* MULEU_S.PH.QBL */
-                     DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-
-                     assign(t0,
-                            unop(Iop_64to32,
-                                 binop(Iop_MullU32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs)))),
-                                       unop(Iop_16Uto32,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t1,
-                            unop(Iop_64to32,
-                                 binop(Iop_MullU32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16to8,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs)))),
-                                       unop(Iop_16Uto32,
-                                            unop(Iop_32to16, getIReg(rt))))));
-
-                     assign(t2, binop(Iop_CmpNE32,
-                                      mkU32(0x0),
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x03ff0000))));
-                     assign(t3, binop(Iop_CmpNE32,
-                                      mkU32(0x0),
-                                      binop(Iop_And32,
-                                            mkexpr(t1),
-                                            mkU32(0x03ff0000))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x200000)),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x200000)),
-                                                         getDSPControl())));
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   IRExpr_ITE(mkexpr(t2),
-                                              mkU16(0xffff),
-                                              unop(Iop_32to16, mkexpr(t0))),
-                                   IRExpr_ITE(mkexpr(t3),
-                                              mkU16(0xffff),
-                                              unop(Iop_32to16, mkexpr(t1)))));
-                     break;
-                  }
-                  case 0x7: {  /* MULEU_S.PH.QBR */
-                     DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-
-                     assign(t0, unop(Iop_64to32,
-                                     binop(Iop_MullU32,
-                                           unop(Iop_8Uto32,
-                                                unop(Iop_16HIto8,
-                                                     unop(Iop_32to16,
-                                                          getIReg(rs)))),
-                                           unop(Iop_16Uto32,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t1, unop(Iop_64to32,
-                                     binop(Iop_MullU32,
-                                           unop(Iop_8Uto32,
-                                                unop(Iop_16to8,
-                                                     unop(Iop_32to16,
-                                                          getIReg(rs)))),
-                                           unop(Iop_16Uto32,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-
-                     assign(t2, binop(Iop_CmpNE32,
-                                      mkU32(0x0),
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x03ff0000))));
-                     assign(t3, binop(Iop_CmpNE32,
-                                      mkU32(0x0),
-                                      binop(Iop_And32,
-                                            mkexpr(t1),
-                                            mkU32(0x03ff0000))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x200000)),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x200000)),
-                                                         getDSPControl())));
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       IRExpr_ITE(mkexpr(t2),
-                                                  mkU16(0xffff),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t0))),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU16(0xffff),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t1)))));
-                     break;
-                  }
-                  case 0x08: {  /* ADDU.PH */
-                     DIP("addu.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-
-                     /* Add lower halves. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Detect overflow. */
-                     assign(t1, binop(Iop_CmpLT32U,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, mkexpr(t0))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs)))));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Add higher halves. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Detect overflow. */
-                     assign(t3, binop(Iop_CmpLT32U,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, mkexpr(t2))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16,
-                                                getIReg(rs)))));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t2)),
-                                       unop(Iop_32to16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x9: {  /* SUBU.PH */
-                     DIP("subu.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-
-                     /* Substract lower halves. */
-                     assign(t0, binop(Iop_Sub32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Detect underflow. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            mkexpr(t0),
-                                            mkU32(0x00010000)),
-                                      mkU32(0x0)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Subtract higher halves. */
-                     assign(t2, binop(Iop_Sub32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Detect underflow. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            mkexpr(t2),
-                                            mkU32(0x00010000)),
-                                      mkU32(0x0)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t2)),
-                                       unop(Iop_32to16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0xA: {  /* ADDQ.PH */
-                     DIP("addq.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-
-                     /* Add lower halves. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t6, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t0))),
-                                      mkU32(0x1)));
-                     /* Detect overflow. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t0),
-                                                  mkU32(0x8000)),
-                                            mkU8(15)),
-                                      mkexpr(t6)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Add higher halves. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t7, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x1)));
-                     /* Detect overflow. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0x00008000)),
-                                            mkU8(15)),
-                                      mkexpr(t7)));
+            default:
+               return -1;
+         }
 
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
+         break;
+      }
 
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t2)),
-                                       unop(Iop_32to16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0xB: {  /* SUBQ.PH */
-                     DIP("subq.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-
-                     /* Subtract lower halves. */
-                     assign(t0, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t6, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t0))),
-                                      mkU32(0x1)));
-                     /* Compare the signs of input value and the result. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t0),
-                                                  mkU32(0x8000)),
-                                            mkU8(15)),
-                                      mkexpr(t6)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Subtract higher halves. */
-                     assign(t2, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t7, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x1)));
-                     /* Compare the signs of input value and the result. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0x00008000)),
-                                            mkU8(15)),
-                                      mkexpr(t7)));
+      case 0x07: {
+         switch (df) {
+            case 0x00: { /* BINSRI.B */
+               DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
+               assign(t1,
+                      binop(Iop_ShlN8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)), mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
+            case 0x01: { /* BINSRI.H */
+               DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
+               assign(t1,
+                      binop(Iop_ShlN16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t2)),
-                                       unop(Iop_32to16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0xC: {  /* ADDU_S.PH */
-                     DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-
-                     /* Add lower halves. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Detect overflow. */
-                     assign(t1, binop(Iop_CmpLT32U,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, mkexpr(t0))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs)))));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Add higher halves. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Detect overflow. */
-                     assign(t3, binop(Iop_CmpLT32U,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, mkexpr(t2))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs)))));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU16(0xffff),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t2))),
-                                       IRExpr_ITE(mkexpr(t1),
-                                                  mkU16(0xffff),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t0)))));
-                     break;
-                  }
-                  case 0xD: {  /* SUBU_S.PH */
-                     DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-
-                     /* Subtract lower halves. */
-                     assign(t0, binop(Iop_Sub32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Detect underflow. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            mkexpr(t0), mkU32(0x00010000)),
-                                      mkU32(0x0)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     /* Subtract higher halves. */
-                     assign(t2, binop(Iop_Sub32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Detect underflow. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            mkexpr(t2), mkU32(0x00010000)),
-                                      mkU32(0x0)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   IRExpr_ITE(mkexpr(t3),
-                                              mkU16(0x0000),
-                                              unop(Iop_32to16, mkexpr(t2))),
-                                   IRExpr_ITE(mkexpr(t1),
-                                              mkU16(0x0000),
-                                              unop(Iop_32to16, mkexpr(t0)))));
-                     break;
-                  }
-                  case 0xE: {  /* ADDQ_S.PH */
-                     DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I16);
-                     t5 = newTemp(Ity_I16);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-
-                     /* Add lower halves. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t6, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t0))),
-                                      mkU32(0x1)));
-                     /* Detect overflow. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t0),
-                                                  mkU32(0x8000)),
-                                            mkU8(15)),
-                                      mkexpr(t6)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     /* Saturate if needed. */
-                     assign(t4, IRExpr_ITE(mkexpr(t1),
-                                           IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                            mkexpr(t6),
-                                                            mkU32(0x0)),
-                                                      mkU16(0x7fff),
-                                                      mkU16(0x8000)),
-                                           unop(Iop_32to16, mkexpr(t0))));
-
-                     /* Add higher halves. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t7, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x1)));
-                     /* Detect overflow. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0x00008000)),
-                                            mkU8(15)),
-                                      mkexpr(t7)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     /* Saturate if needed. */
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                            mkexpr(t7),
-                                                            mkU32(0x0)),
-                                                      mkU16(0x7fff),
-                                                      mkU16(0x8000)),
-                                           unop(Iop_32to16, mkexpr(t2))));
-
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
-                     break;
-                  }
-                  case 0xF: {  /* SUBQ_S.PH */
-                     DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I16);
-                     t5 = newTemp(Ity_I16);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-
-                     /* Subtract lower halves. */
-                     assign(t0, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t6, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t0))),
-                                      mkU32(0x1)));
-                     /* Detect overflow or underflow. */
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t0),
-                                                  mkU32(0x8000)),
-                                            mkU8(15)),
-                                      mkexpr(t6)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     /* Saturate if needed. */
-                     assign(t4, IRExpr_ITE(mkexpr(t1),
-                                           IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                            mkexpr(t6),
-                                                            mkU32(0x0)),
-                                                      mkU16(0x7fff),
-                                                      mkU16(0x8000)),
-                                           unop(Iop_32to16, mkexpr(t0))));
-
-                     /* Subtract higher halves. */
-                     assign(t2, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Bit 16 of the result. */
-                     assign(t7, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x1)));
-                     /* Detect overflow or underflow. */
-                     assign(t3, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  mkexpr(t2),
-                                                  mkU32(0x00008000)),
-                                            mkU8(15)),
-                                      mkexpr(t7)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     /* Saturate if needed. */
-                     assign(t5, IRExpr_ITE(mkexpr(t3),
-                                           IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                            mkexpr(t7),
-                                                            mkU32(0x0)),
-                                                      mkU16(0x7fff),
-                                                      mkU16(0x8000)),
-                                           unop(Iop_32to16, mkexpr(t2))));
-
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
-                     break;
-                  }
-                  case 0x10: {  /* ADDSC */
-                     DIP("addsc r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-
-                     /* The carry bit result out of the addition operation is
-                        written to bit 13(the c field) of the DSPControl reg. */
-                     assign(t0, binop(Iop_Add64,
-                                      unop(Iop_32Uto64, getIReg(rs)),
-                                      unop(Iop_32Uto64, getIReg(rt))));
-
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t0)),
-                                            mkU32(0x1)),
-                                      mkU32(0x1)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x2000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xffffdfff))));
-
-                     putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
-                     break;
-                  }
-                  case 0x11: {  /* ADDWC */
-                     DIP("addwc r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I1);
-
-                     /* Get carry bit from DSPControl register. */
-                     assign(t0, binop(Iop_Shr32,
-                                       binop(Iop_And32,
-                                             getDSPControl(),
-                                             mkU32(0x2000)),
-                                       mkU8(0xd)));
-                     assign(t1, binop(Iop_Add64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64,
-                                           binop(Iop_Add32,
-                                                 getIReg(rt),
-                                                 mkexpr(t0)))));
-
-                     /* Extract bits 32 and 31. */
-                     assign(t2, binop(Iop_And32,
-                                      unop(Iop_64HIto32, mkexpr(t1)),
-                                      mkU32(0x1)));
-                     assign(t3, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32, mkexpr(t1)),
-                                            mkU32(0x80000000)),
-                                      mkU8(31)));
-                     assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-                     putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
-                     break;
-                  }
-                  case 0x12: {  /* MODSUB */
-                     DIP("modsub r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-
-                     /* decr_7..0 */
-                     assign(t0,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16to8,
-                                      unop(Iop_32to16, getIReg(rt)))));
-
-                     /* lastindex_15..0 */
-                     assign(t1,
-                            unop(Iop_16Uto32,
-                                 binop(Iop_8HLto16,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))),
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     /* temp_15..0 */
-                     assign(t2,
-                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                             getIReg(rs),
-                                             mkU32(0x00000000)),
-                                       mkexpr(t1),
-                                       binop(Iop_Sub32,
-                                             getIReg(rs), mkexpr(t0))));
-                     putIReg(rd, mkexpr(t2));
-                     break;
-                  }
-                  case 0x14: {  /* RADDU.W.QB */
-                     DIP("raddu.w.qb r%u, r%u", rd, rs);
-                     vassert(!mode64);
-                     putIReg(rd, binop(Iop_Add32,
-                                       binop(Iop_Add32,
-                                             unop(Iop_8Uto32,
-                                                  unop(Iop_16to8,
-                                                       unop(Iop_32to16,
-                                                            getIReg(rs)))),
-                                             unop(Iop_8Uto32,
-                                                  unop(Iop_16HIto8,
-                                                       unop(Iop_32to16,
-                                                            getIReg(rs))))),
-                                       binop(Iop_Add32,
-                                             unop(Iop_8Uto32,
-                                                  unop(Iop_16to8,
-                                                       unop(Iop_32HIto16,
-                                                            getIReg(rs)))),
-                                             unop(Iop_8Uto32,
-                                                  unop(Iop_16HIto8,
-                                                       unop(Iop_32HIto16,
-                                                            getIReg(rs)))))));
-                     break;
-                  }
-                  case 0x16: {  /* ADDQ_S.W */
-                     DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_Add64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-
-                     assign(t3, binop(Iop_And32,
-                                      unop(Iop_64HIto32, mkexpr(t0)),
-                                      mkU32(0x1)));
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t0)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      mkexpr(t3)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             mkexpr(t3),
-                                                             mkU32(0x0)),
-                                                       mkU32(0x7fffffff),
-                                                       mkU32(0x80000000)),
-                                            unop(Iop_64to32, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x17: {  /* SUBQ_S.W */
-                     DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_Sub64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-
-                     assign(t3, binop(Iop_And32,
-                                      unop(Iop_64HIto32, mkexpr(t0)),
-                                      mkU32(0x1)));
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t0)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      mkexpr(t3)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00100000)),
-                                              getDSPControl()));
-
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                             mkexpr(t3),
-                                                             mkU32(0x0)),
-                                                       mkU32(0x7fffffff),
-                                                       mkU32(0x80000000)),
-                                            unop(Iop_64to32, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x1C: {  /* MULEQ_S.W.PHL */
-                     DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I32);
-
-                     assign(t0,
-                            binop(Iop_Shl32,
-                                  binop(Iop_Mul32,
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32HIto16, getIReg(rt))),
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32HIto16, getIReg(rs)))),
-                                  mkU8(0x1)));
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0xffff0000)),
-                                      mkU32(0x80000000)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0xffff0000)),
-                                      mkU32(0x80000000)));
-                     assign(t3, IRExpr_ITE(mkexpr(t1),
-                                           IRExpr_ITE(mkexpr(t2),
-                                                      binop(Iop_Or32,
-                                                            getDSPControl(),
-                                                            mkU32(0x00200000)),
-                                                      getDSPControl()),
-                                           getDSPControl()));
-                     putDSPControl(mkexpr(t3));
-
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(mkexpr(t2),
-                                                       mkU32(0x7fffffff),
-                                                       mkexpr(t0)),
-                                            mkexpr(t0)));
-                     break;
-                  }
-                  case 0x1D: {  /* MULEQ_S.W.PHR */
-                     DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t0,
-                            binop(Iop_Shl32,
-                                  binop(Iop_Mul32,
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32to16, getIReg(rt))),
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32to16, getIReg(rs)))),
-                                  mkU8(0x1)));
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0xffff)),
-                                      mkU32(0x8000)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0xffff)),
-                                      mkU32(0x8000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              IRExpr_ITE(mkexpr(t2),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(mkexpr(t2),
-                                                       mkU32(0x7fffffff),
-                                                       mkexpr(t0)),
-                                            mkexpr(t0)));
-                     break;
-                  }
-                  case 0x1E: {  /* MULQ_S.PH */
-                     DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I16);
-                     t3 = newTemp(Ity_I16);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t5,
-                            unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
-                     assign(t6,
-                            unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
-
-                     assign(t7,
-                            unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
-                     assign(t8,
-                            unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
-
-                     assign(t0, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t5),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000))),
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t6),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000)))));
-                     assign(t1, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t7),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000))),
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t8),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000)))));
+            case 0x02: { /* BINSRI.W */
+               DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
+               assign(t1,
+                      binop(Iop_ShlN32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_Or32,
-                                                          mkexpr(t0),
-                                                          mkexpr(t1)),
-                                                    mkU32(0x0)),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x200000))));
-
-                     assign(t2, unop(Iop_32HIto16,
-                                     binop(Iop_Shl32,
-                                           unop(Iop_64to32,
-                                                binop(Iop_MullS32,
-                                                      mkexpr(t7),
-                                                      mkexpr(t8))),
-                                           mkU8(0x1))));
-                     assign(t3, unop(Iop_32HIto16,
-                                     binop(Iop_Shl32,
-                                           unop(Iop_64to32,
-                                                binop(Iop_MullS32,
-                                                      mkexpr(t5),
-                                                      mkexpr(t6))),
-                                           mkU8(0x1))));
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        mkexpr(t1),
-                                                        mkU32(0x0)),
-                                                  mkexpr(t2),
-                                                  mkU16(0x7fff)),
-                                       IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        mkexpr(t0),
-                                                        mkU32(0x0)),
-                                                  mkexpr(t3),
-                                                  mkU16(0x7fff))));
-                     break;
-                  }
-                  case 0x1F: {  /* MULQ_RS.PH */
-                     DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I16);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I16);
-
-                     /* Multiply and round lower halfwords. */
-                     assign(t0, binop(Iop_Add32,
-                                      binop(Iop_Shl32,
-                                            binop(Iop_Mul32,
-                                                  unop(Iop_16Sto32,
-                                                       unop(Iop_32to16,
-                                                            getIReg(rt))),
-                                                  unop(Iop_16Sto32,
-                                                       unop(Iop_32to16,
-                                                            getIReg(rs)))),
-                                            mkU8(0x1)),
-                                      mkU32(0x00008000)));
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rt), mkU32(0xffff)),
-                                      mkU32(0x8000)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rs), mkU32(0xffff)),
-                                      mkU32(0x8000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              IRExpr_ITE(mkexpr(t2),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     assign(t3, IRExpr_ITE(mkexpr(t1),
-                                           IRExpr_ITE(mkexpr(t2),
-                                                      mkU16(0x7fff),
-                                                      unop(Iop_32HIto16,
-                                                           mkexpr(t0))),
-                                           unop(Iop_32HIto16, mkexpr(t0))));
-
-                     /* Multiply and round higher halfwords. */
-                     assign(t4, binop(Iop_Add32,
-                                      binop(Iop_Shl32,
-                                            binop(Iop_Mul32,
-                                                  unop(Iop_16Sto32,
-                                                       unop(Iop_32HIto16,
-                                                            getIReg(rt))),
-                                                  unop(Iop_16Sto32,
-                                                       unop(Iop_32HIto16,
-                                                            getIReg(rs)))),
-                                            mkU8(0x1)),
-                                      mkU32(0x00008000)));
-                     assign(t5, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0xffff0000)),
-                                      mkU32(0x80000000)));
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0xffff0000)),
-                                      mkU32(0x80000000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t5),
-                                             IRExpr_ITE(mkexpr(t6),
-                                                        binop(Iop_Or32,
-                                                             getDSPControl(),
-                                                             mkU32(0x00200000)),
-                                                        getDSPControl()),
-                                             getDSPControl()));
-                     assign(t7, IRExpr_ITE(mkexpr(t5),
-                                           IRExpr_ITE(mkexpr(t6),
-                                                      mkU16(0x7fff),
-                                                      unop(Iop_32HIto16,
-                                                           mkexpr(t4))),
-                                           unop(Iop_32HIto16, mkexpr(t4))));
-
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of ADDU.QB */
-            }
-            case 0x11: {  /* CMPU.EQ.QB */
-               switch(sa) {
-                  case 0x0: {  /* CMPU.EQ.QB */
-                     DIP("cmpu.eq.qb r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
+            case 0x03: { /* BINSRI.D */
+               DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = -2;
+               assign(t1,
+                      binop(Iop_ShlN64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-                     assign(t1,
-                            binop(Iop_CmpEQ32,
-                                  binop(Iop_And32, getIReg(rs), mkU32(0xff)),
-                                  binop(Iop_And32, getIReg(rt), mkU32(0xff))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-                     break;
-                  }
-                  case 0x1: {  /* CMPU.LT.QB */
-                     DIP("cmpu.lt.qb r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-
-                     assign(t1, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-                     break;
-                  }
-                  case 0x2: {  /* CMPU.LE.QB */
-                     DIP("cmpu.le.qb r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-
-                     assign(t1, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-                     break;
-                  }
-                  case 0x3: {  /* PICK.QB */
-                     DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I8);
+            default:
+               return -1;
+         }
 
-                     assign(t0, getDSPControl());
-                     assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x01000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_16to8,
-                                                 unop(Iop_32to16,
-                                                      getIReg(rs))),
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt)))));
-                     assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x02000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs))),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt)))));
-                     assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x04000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs))),
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt)))));
-                     assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x08000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs))),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt)))));
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
-                                   binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
-                     break;
-                  }
-                  case 0x4: {  /* CMPGU.EQ.QB */
-                     DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001), mkU32(0)));
-
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-
-                     assign(t4, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  case 0x5: {  /* CMPGU.LT.QB */
-                     DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t1, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001), mkU32(0)));
-
-                     assign(t2, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-
-                     assign(t3, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-
-                     assign(t4, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  case 0x6: {  /* CMPGU.LE.QB */
-                     DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t1, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001), mkU32(0)));
-
-                     assign(t2, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-
-                     assign(t3, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-
-                     assign(t4, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  case 0x8: {  /* CMP.EQ.PH */
-                     DIP("cmp.eq.ph r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t1, binop(Iop_CmpEQ16,
-                                      unop(Iop_32to16, getIReg(rs)),
-                                      unop(Iop_32to16, getIReg(rt))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-                     assign(t2, binop(Iop_CmpEQ16,
-                                      unop(Iop_32HIto16, getIReg(rs)),
-                                      unop(Iop_32HIto16, getIReg(rt))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-                     break;
-                  }
-                  case 0x9: {  /* CMP.LT.PH */
-                     DIP("cmp.lt.ph r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t1, binop(Iop_CmpLT32S,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLT32S,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-                     break;
-                  }
-                  case 0xA: {  /* CMP.LE.PH */
-                     DIP("cmp.le.ph r%u, r%u", rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t1, binop(Iop_CmpLE32S,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLE32S,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-                     break;
-                  }
-                  case 0xB: {  /* PICK.PH */
-                     DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I16);
-                     t2 = newTemp(Ity_I16);
+         break;
+      }
 
-                     assign(t0, getDSPControl());
+      default:
+         return -1;
+   }
 
-                     assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x01000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_32to16, getIReg(rs)),
-                                           unop(Iop_32to16, getIReg(rt))));
+   return 0;
+}
 
-                     assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x02000000)),
-                                                 mkU32(0x0)),
-                                           unop(Iop_32HIto16, getIReg(rs)),
-                                           unop(Iop_32HIto16, getIReg(rt))));
+static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws)   /* BIT (0x0A) */
+{
+   IRTemp t1, t2;
+   UShort operation;
+   UChar df, m;
 
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
-                  case 0xC: {  /* PRECRQ.QB.PH */
-                     DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt);
-                     vassert(!mode64);
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_16HIto8,
-                                              unop(Iop_32HIto16, getIReg(rs))),
-                                         unop(Iop_16HIto8,
-                                              unop(Iop_32to16, getIReg(rs)))),
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_16HIto8,
-                                              unop(Iop_32HIto16, getIReg(rt))),
-                                         unop(Iop_16HIto8,
-                                              unop(Iop_32to16, getIReg(rt))))));
-                     break;
-                  }
-                  case 0xD: {  /* PRECR.QB.PH */
-                     DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_16to8,
-                                              unop(Iop_32HIto16, getIReg(rs))),
-                                         unop(Iop_16to8,
-                                              unop(Iop_32to16, getIReg(rs)))),
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_16to8,
-                                              unop(Iop_32HIto16, getIReg(rt))),
-                                         unop(Iop_16to8,
-                                              unop(Iop_32to16, getIReg(rt))))));
-                     break;
-                  }
-                  case 0xF: {  /* PRECRQU_S.QB.PH */
-                     DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I8);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I8);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I8);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I8);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I32);
-                     t13 = newTemp(Ity_I8);
-                     t14 = newTemp(Ity_I1);
-                     t15 = newTemp(Ity_I32);
-
-                     assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                 mkU32(0x7f80),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32to16,
-                                                            getIReg(rs))),
-                                                       mkU32(0x7fff))),
-                                           mkU8(0xff),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     binop(Iop_Shl32,
-                                                           getIReg(rs),
-                                                           mkU8(1))))));
-                     assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32to16,
-                                                                 getIReg(rs))),
-                                                       mkU32(0x00008000)),
-                                                 mkU32(0x0)),
-                                           mkexpr(t4),
-                                           mkU8(0x0)));
-                     assign(t5, binop(Iop_And32,
-                                      unop(Iop_16Uto32,
-                                            unop(Iop_32to16,
-                                                 getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t6, binop(Iop_CmpLT32U,
-                                      mkU32(0x7f80),
-                                      binop(Iop_And32,
-                                            unop(Iop_16Uto32,
-                                                 unop(Iop_32to16,
-                                                 getIReg(rs))),
-                                            mkU32(0x7fff))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    mkexpr(t5),
-                                                    mkU32(0x0)),
-                                              IRExpr_ITE(mkexpr(t6),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00400000)
-                                                              ),
-                                                         getDSPControl()),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00400000))));
-
-                     assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                 mkU32(0x7f80),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32HIto16,
-                                                                 getIReg(rs))),
-                                                       mkU32(0x7fff))),
-                                           mkU8(0xff),
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     binop(Iop_Shl32,
-                                                           getIReg(rs),
-                                                           mkU8(1))))));
-                     assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32HIto16,
-                                                                 getIReg(rs))),
-                                                       mkU32(0x00008000)),
-                                                 mkU32(0x0)),
-                                           mkexpr(t7),
-                                           mkU8(0x0)));
-                     assign(t8, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            unop(Iop_16Uto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs))),
-                                            mkU32(0x00008000)),
-                                      mkU32(0x0)));
-                     assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                 mkU32(0x7f80),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32HIto16,
-                                                                 getIReg(rs))),
-                                                       mkU32(0x7fff))),
-                                           binop(Iop_Or32,
-                                                 getDSPControl(),
-                                                 mkU32(0x00400000)),
-                                           getDSPControl()));
-                     putDSPControl(IRExpr_ITE(mkexpr(t8),
-                                              mkexpr(t9),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00400000))));
-
-                     assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                  mkU32(0x7f80),
-                                                  binop(Iop_And32,
-                                                        unop(Iop_16Uto32,
-                                                             unop(Iop_32to16,
-                                                             getIReg(rt))),
-                                                        mkU32(0x7fff))),
-                                            mkU8(0xff),
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32to16,
-                                                      binop(Iop_Shl32,
-                                                            getIReg(rt),
-                                                            mkU8(1))))));
-                     assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32to16,
-                                                                 getIReg(rt))),
-                                                       mkU32(0x00008000)),
-                                                 mkU32(0x0)),
-                                           mkexpr(t10),
-                                           mkU8(0x0)));
-                     assign(t11, binop(Iop_CmpEQ32,
-                                       binop(Iop_And32,
-                                             unop(Iop_16Uto32,
-                                                  unop(Iop_32to16,
-                                                       getIReg(rt))),
-                                             mkU32(0x00008000)),
-                                       mkU32(0x0)));
-                     assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                  mkU32(0x7f80),
-                                                  binop(Iop_And32,
-                                                        unop(Iop_16Uto32,
-                                                             unop(Iop_32to16,
-                                                             getIReg(rt))),
-                                                        mkU32(0x7fff))),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  mkU32(0x00400000)),
-                                            getDSPControl()));
-                     putDSPControl(IRExpr_ITE(mkexpr(t11),
-                                              mkexpr(t12),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00400000))));
-
-                     assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                  mkU32(0x7f80),
-                                                  binop(Iop_And32,
-                                                        unop(Iop_16Uto32,
-                                                             unop(Iop_32HIto16,
-                                                                  getIReg(rt))),
-                                                        mkU32(0x7fff))),
-                                            mkU8(0xff),
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32HIto16,
-                                                      binop(Iop_Shl32,
-                                                            getIReg(rt),
-                                                            mkU8(1))))));
-                     assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_16Uto32,
-                                                            unop(Iop_32HIto16,
-                                                                 getIReg(rt))),
-                                                       mkU32(0x00008000)),
-                                                 mkU32(0x0)),
-                                           mkexpr(t13),
-                                           mkU8(0x0)));
-                     assign(t14, binop(Iop_CmpEQ32,
-                                       binop(Iop_And32,
-                                             unop(Iop_16Uto32,
-                                                  unop(Iop_32HIto16,
-                                                       getIReg(rt))),
-                                             mkU32(0x00008000)),
-                                       mkU32(0x0)));
-                     assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
-                                                  mkU32(0x7f80),
-                                                  binop(Iop_And32,
-                                                        unop(Iop_16Uto32,
-                                                             unop(Iop_32HIto16,
-                                                                  getIReg(rt))),
-                                                        mkU32(0x7fff))),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  mkU32(0x00400000)),
-                                            getDSPControl()));
-                     putDSPControl(IRExpr_ITE(mkexpr(t14),
-                                              mkexpr(t15),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00400000))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t1), mkexpr(t0)),
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t3), mkexpr(t2))));
-                     break;
-                  }
-                  case 0x14: {  /* PRECRQ.PH.W */
-                     DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt);
-                     vassert(!mode64);
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32HIto16, getIReg(rs)),
-                                       unop(Iop_32HIto16, getIReg(rt))));
-                     break;
-                  }
-                  case 0x15: {  /* PRECRQ_RS.PH.W */
-                     DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x007F0000) >> 16;
 
-                     assign(t0, binop(Iop_Add64,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_Shr32,
-                                                  binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x80000000)),
-                                                  mkU8(31)),
-                                            getIReg(rs)),
-                                      mkU64(0x0000000000008000ULL)));
-                     assign(t1, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t0)),
-                                            mkU32(0x1)),
-                                      binop(Iop_And32,
-                                            binop(Iop_Shr32,
-                                                  unop(Iop_64to32, mkexpr(t0)),
-                                                  mkU8(31)),
-                                            mkU32(0x1))));
-                     assign(t2, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x7fffffff),
-                                           unop(Iop_64to32, mkexpr(t0))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                     assign(t3, binop(Iop_Add64,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_Shr32,
-                                                  binop(Iop_And32,
-                                                        getIReg(rt),
-                                                        mkU32(0x80000000)),
-                                                  mkU8(31)),
-                                            getIReg(rt)),
-                                      mkU64(0x0000000000008000ULL)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t3)),
-                                            mkU32(0x1)),
-                                      binop(Iop_And32,
-                                            binop(Iop_Shr32,
-                                                  unop(Iop_64to32, mkexpr(t3)),
-                                                  mkU8(31)),
-                                            mkU32(0x1))));
-                     assign(t5, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x7fffffff),
-                                           unop(Iop_64to32, mkexpr(t3))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32HIto16, mkexpr(t2)),
-                                       unop(Iop_32HIto16, mkexpr(t5))));
-                     break;
-                  }
-                  case 0x1E: {  /* PRECR_SRA.PH.W */
-                     DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd);
-                     vassert(!mode64);
-
-                     if (0 == rd) {
-                        putIReg(rt, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, getIReg(rt)),
-                                          unop(Iop_32to16, getIReg(rs))));
-                     } else {
-                        putIReg(rt, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, binop(Iop_Sar32,
-                                                                 getIReg(rt),
-                                                                 mkU8(rd))),
-                                          unop(Iop_32to16, binop(Iop_Sar32,
-                                                                 getIReg(rs),
-                                                                 mkU8(rd)))));
-                     }
-                     break;
-                  }
-                  case 0x1F: {  /* PRECR_SRA_R.PH.W */
-                     DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd);
-                     vassert(!mode64);
+   if ((df & 0x70) == 0x70) {        // 111mmmm; b
+      m = df & 0x07;
+      df = 0;
+   } else if ((df & 0x60) == 0x60) { // 110mmmm; h
+      m = df & 0x0F;
+      df = 1;
+   } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
+      m = df & 0x1F;
+      df = 2;
+   } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
+      m = df & 0x3F;
+      df = 3;
+   }
 
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
+   switch (operation) {
+      case 0x00: { /* SAT_S.df */
+         switch (df) {
+            case 0x00: { /* SAT_S.B */
+               DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
 
-                     if (0 == rd) {
-                        putIReg(rt, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, getIReg(rt)),
-                                          unop(Iop_32to16, getIReg(rs))));
-                     } else {
-                        assign(t0, binop(Iop_Shr32,
-                                         binop(Iop_Add32,
-                                               binop(Iop_Sar32,
-                                                     getIReg(rt),
-                                                     mkU8(rd-1)),
-                                               mkU32(0x1)),
-                                         mkU8(0x1)));
-                        assign(t1, binop(Iop_Shr32,
-                                         binop(Iop_Add32,
-                                               binop(Iop_Sar32,
-                                                     getIReg(rs),
-                                                     mkU8(rd-1)),
-                                               mkU32(0x1)),
-                                         mkU8(0x1)));
-                        putIReg(rt, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, mkexpr(t0)),
-                                          unop(Iop_32to16, mkexpr(t1))));
-                     };
-                     break;
-                  }
-                  case 0xE: {  /* PACKRL.PH */
-                     DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
+               if (m == 0) {
+                  putWReg(wd, mkexpr(t1));
+               } else {
+                  t2 = newTemp(Ity_V128);
+                  assign(t2,
+                         binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_OrV128,
+                                      binop(Iop_AndV128,
+                                            binop(Iop_CmpEQ8x16,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            getWReg(ws)),
+                                      binop(Iop_ShlN8x16,
+                                            binop(Iop_CmpGT8Sx16,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(m))),
+                                binop(Iop_ShrN8x16,
+                                      binop(Iop_CmpGT8Sx16,
+                                            mkexpr(t2),
+                                            mkexpr(t1)),
+                                      mkU8(8 - m))));
+               }
 
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, getIReg(rs)),
-                                       unop(Iop_32HIto16, getIReg(rt))));
-                     break;
-                  }
-                  case 0x18: {  /* CMPGDU.EQ.QB */
-                     DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
+               break;
+            }
 
-                     assign(t1,
-                            binop(Iop_CmpEQ32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpEQ32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  case 0x19: {  /* CMPGDU.LT.QB */
-                     DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t1, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpLT32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  case 0x1A: {  /* CMPGDU.LE.QB */
-                     DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-
-                     assign(t1, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           mkU32(0x00000001),
-                                           mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x01000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfeffffff))));
-
-                     assign(t2, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16,
-                                                     getIReg(rt))))));
-                     assign(t6, IRExpr_ITE(mkexpr(t2),
-                                           mkU32(0x00000002), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x02000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfdffffff))));
-
-                     assign(t3, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16to8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t7, IRExpr_ITE(mkexpr(t3),
-                                           mkU32(0x00000004), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x04000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xfbffffff))));
-
-                     assign(t4, binop(Iop_CmpLE32U,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rs)))),
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32HIto16,
-                                                     getIReg(rt))))));
-                     assign(t8, IRExpr_ITE(mkexpr(t4),
-                                           mkU32(0x00000008), mkU32(0)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t4),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x08000000)),
-                                              binop(Iop_And32,
-                                                    getDSPControl(),
-                                                    mkU32(0xf7ffffff))));
-
-                     putIReg(rd, binop(Iop_Or32,
-                                       binop(Iop_Or32,
-                                             binop(Iop_Or32,
-                                                   mkexpr(t5), mkexpr(t6)),
-                                             mkexpr(t7)),
-                                       mkexpr(t8)));
-                     break;
-                  }
-                  default:
-                     return -1;
+            case 0x01: { /* SAT_S.H */
+               DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
+
+               if (m == 0) {
+                  putWReg(wd, mkexpr(t1));
+               } else {
+                  t2 = newTemp(Ity_V128);
+                  assign(t2,
+                         binop(Iop_SarN16x8,
+                               getWReg(ws),
+                               mkU8(m)));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_OrV128,
+                                      binop(Iop_AndV128,
+                                            binop(Iop_CmpEQ16x8,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            getWReg(ws)),
+                                      binop(Iop_ShlN16x8,
+                                            binop(Iop_CmpGT16Sx8,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(m))),
+                                binop(Iop_ShrN16x8,
+                                      binop(Iop_CmpGT16Sx8,
+                                            mkexpr(t2),
+                                            mkexpr(t1)),
+                                      mkU8(16 - m))));
+               }
+
+               break;
+            }
+
+            case 0x02: { /* SAT_S.W */
+               DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
+
+               if (m == 0) {
+                  putWReg(wd, mkexpr(t1));
+               } else {
+                  t2 = newTemp(Ity_V128);
+                  assign(t2,
+                         binop(Iop_SarN32x4,
+                               getWReg(ws),
+                               mkU8(m)));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_OrV128,
+                                      binop(Iop_AndV128,
+                                            binop(Iop_CmpEQ32x4,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            getWReg(ws)),
+                                      binop(Iop_ShlN32x4,
+                                            binop(Iop_CmpGT32Sx4,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(m))),
+                                binop(Iop_ShrN32x4,
+                                      binop(Iop_CmpGT32Sx4,
+                                            mkexpr(t2),
+                                            mkexpr(t1)),
+                                      mkU8(32 - m))));
+               }
+
+               break;
+            }
+
+            case 0x03: { /* SAT_S.D */
+               DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+
+               if (m == 0) {
+                  putWReg(wd, mkexpr(t1));
+               } else {
+                  t2 = newTemp(Ity_V128);
+                  assign(t2,
+                         binop(Iop_SarN64x2,
+                               getWReg(ws),
+                               mkU8(m)));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_OrV128,
+                                      binop(Iop_AndV128,
+                                            binop(Iop_CmpEQ64x2,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            getWReg(ws)),
+                                      binop(Iop_ShlN64x2,
+                                            binop(Iop_CmpGT64Sx2,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(m))),
+                                binop(Iop_ShrN64x2,
+                                      binop(Iop_CmpGT64Sx2,
+                                            mkexpr(t2),
+                                            mkexpr(t1)),
+                                      mkU8(64 - m))));
                }
-               break;  /* end of CMPU.EQ.QB */
-            }
-            case 0x13: {  /* SHLL.QB */
-               switch(sa) {
-                  case 0x0: {  /* SHLL.QB */
-                     DIP("shll.qb r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I1);
-                     t10 = newTemp(Ity_I1);
-
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        /* Shift bits 7..0 and 23..16. */
-                        assign(t0, binop(Iop_Shl32,
-                                         binop(Iop_And32,
-                                               getIReg(rt),
-                                               mkU32(0x00ff00ff)),
-                                         mkU8(rs)));
-                        assign(t1, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t0),
-                                              mkU32(0xff000000)),
-                                        mkU32(0x00000000)));
-                        assign(t2, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t0),
-                                              mkU32(0xff000000)),
-                                        mkU32(0xff000000)));
-                        assign(t7, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t0),
-                                              mkU32(0x0000ff00)),
-                                        mkU32(0x00000000)));
-                        assign(t8, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t0),
-                                              mkU32(0x0000ff00)),
-                                        mkU32(0x000ff00)));
-                        /* Shift bits 15..8 and 31..24. */
-                        assign(t3, binop(Iop_Shl32,
-                                         binop(Iop_Shr32,
-                                               binop(Iop_And32,
-                                                     getIReg(rt),
-                                                     mkU32(0xff00ff00)),
-                                               mkU8(8)),
-                                         mkU8(rs)));
-                        assign(t4, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t3),
-                                              mkU32(0xff000000)),
-                                        mkU32(0x00000000)));
-                        assign(t5, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t3),
-                                              mkU32(0xff000000)),
-                                        mkU32(0xff000000)));
-                        assign(t9, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t3),
-                                              mkU32(0x0000ff00)),
-                                        mkU32(0x00000000)));
-                        assign(t10, binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              mkexpr(t3),
-                                              mkU32(0x0000ff00)),
-                                        mkU32(0x0000ff00)));
-
-                        assign(t6, binop(Iop_Or32,
-                                         binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t1)),
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t2))),
-                                               binop(Iop_And32,
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t7)),
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t8)))),
-                                         binop(Iop_Or32,
-                                               binop(Iop_And32,
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t4)),
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t5))),
-                                               binop(Iop_And32,
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t9)),
-                                                     unop(Iop_1Uto32,
-                                                          mkexpr(t10))))));
-
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       mkexpr(t6),
-                                                       mkU32(0x0)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putIReg(rd, binop(Iop_Or32,
-                                          binop(Iop_Shl32,
-                                                binop(Iop_And32,
-                                                      mkexpr(t3),
-                                                      mkU32(0x00ff00ff)),
-                                                mkU8(8)),
-                                          binop(Iop_And32,
-                                                mkexpr(t0),
-                                                mkU32(0x00ff00ff))));
-                     }
-                     break;
-                  }
-                  case 0x3: {  /* SHRL.QB */
-                     DIP("shrl.qb r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I8);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I8);
-                     t9 = newTemp(Ity_I32);
-
-                     assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
-                     assign(t0, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t1, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           mkexpr(t0),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-
-                     assign(t2, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t3, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           mkexpr(t2),
-                                           unop(Iop_32to8, mkexpr(t9)))));
 
-                     assign(t4, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t5, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           mkexpr(t4),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-
-                     assign(t6, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t7, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           mkexpr(t6),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-                     putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  mkexpr(t9),
-                                                  mkU32(0x0)),
-                                            getIReg(rt),
-                                            binop(Iop_16HLto32,
-                                                  binop(Iop_8HLto16,
-                                                        mkexpr(t7),
-                                                        mkexpr(t5)),
-                                                  binop(Iop_8HLto16,
-                                                        mkexpr(t3),
-                                                        mkexpr(t1)))));
-                     break;
-                  }
-                  case 0x2: {  /* SHLLV.QB */
-                     DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I1);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I8);
-
-                     assign(t11, unop(Iop_32to8,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0x7))));
-                     /* Shift bits 7..0 and 23..16. */
-                     assign(t0, binop(Iop_Shl32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0x00ff00ff)),
-                                      mkexpr(t11)));
-                     assign(t1, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t0),
-                                           mkU32(0xff000000)),
-                                     mkU32(0x00000000)));
-                     assign(t2, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t0),
-                                           mkU32(0xff000000)),
-                                     mkU32(0xff000000)));
-                     assign(t7, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t0),
-                                           mkU32(0x0000ff00)),
-                                     mkU32(0x00000000)));
-                     assign(t8, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t0),
-                                           mkU32(0x0000ff00)),
-                                     mkU32(0x000ff00)));
-                     /* Shift bits 15..8 and 31..24. */
-                     assign(t3, binop(Iop_Shl32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0xff00ff00)),
-                                            mkU8(8)),
-                                      mkexpr(t11)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t3),
-                                           mkU32(0xff000000)),
-                                     mkU32(0x00000000)));
-                     assign(t5, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t3),
-                                           mkU32(0xff000000)),
-                                     mkU32(0xff000000)));
-                     assign(t9, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t3),
-                                           mkU32(0x0000ff00)),
-                                     mkU32(0x00000000)));
-                     assign(t10, binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           mkexpr(t3),
-                                           mkU32(0x0000ff00)),
-                                     mkU32(0x0000ff00)));
+               break;
+            }
+         }
 
-                     assign(t6, binop(Iop_Or32,
-                                      binop(Iop_Or32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t1)),
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t2))),
-                                            binop(Iop_And32,
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t7)),
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t8)))),
-                                      binop(Iop_Or32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t4)),
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t5))),
-                                            binop(Iop_And32,
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t9)),
-                                                  unop(Iop_1Uto32,
-                                                       mkexpr(t10))))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t6),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                     putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  unop(Iop_8Uto32, mkexpr(t11)),
-                                                  mkU32(0)),
-                                            getIReg(rt),
-                                            binop(Iop_Or32,
-                                                  binop(Iop_Shl32,
-                                                        binop(Iop_And32,
-                                                              mkexpr(t3),
-                                                              mkU32(0xff00ff)),
-                                                        mkU8(8)),
-                                                  binop(Iop_And32,
-                                                        mkexpr(t0),
-                                                        mkU32(0x00ff00ff)))));
-                     break;
-                  }
-                  case 0x1: {  /* SHRLV.QB */
-                     DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I8);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I8);
+         break;
+      }
 
-                     assign(t0, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           unop(Iop_8Uto32,
-                                                unop(Iop_32to8, getIReg(rt))),
-                                           mkU8(rs))));
-                     assign(t1, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           unop(Iop_8Uto32,
-                                                unop(Iop_16HIto8,
-                                                     unop(Iop_32to16,
-                                                          getIReg(rt)))),
-                                           mkU8(rs))));
-                     assign(t2, unop(Iop_32to8,
-                                      binop(Iop_Shr32,
-                                            unop(Iop_8Uto32,
-                                                 unop(Iop_16to8,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rt)))),
-                                            mkU8(rs))));
-                     assign(t3, unop(Iop_32to8,
-                                     binop(Iop_Shr32,
-                                           unop(Iop_8Uto32,
-                                                unop(Iop_16HIto8,
-                                                     unop(Iop_32HIto16,
-                                                          getIReg(rt)))),
-                                           mkU8(rs))));
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
-                     break;
-                  }
-                  case 0x4: {  /* SHRA.QB */
-                     DIP("shra.qb r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
-
-                     /* ========== GPR[rt]_31..24 ========== */
-                     assign(t1,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16HIto8,
-                                      unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t2,
-                            binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
-                     /* tempD_7..0 */
-                     assign(t0,
-                            binop(Iop_Or32,
-                                  mkexpr(t2),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t1),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
-                     /* ========== GPR[rt]_23..16 ========== */
-                     assign(t4,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16to8,
-                                      unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
-                     /* tempC_7..0 */
-                     assign(t3,
-                            binop(Iop_Or32,
-                                  mkexpr(t5),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t4),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
-                     /* ========== GPR[rt]_15..8 ========== */
-                     assign(t7,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16HIto8,
-                                      unop(Iop_32to16, getIReg(rt)))));
-                     assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
-                     /* tempB_7..0 */
-                     assign(t6,
-                            binop(Iop_Or32,
-                                  mkexpr(t8),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t7),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
-                     /* ========== GPR[rt]_7..0 ========== */
-                     assign(t10,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16to8,
-                                      unop(Iop_32to16, getIReg(rt)))));
-                     assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
-                     /* tempB_7..0 */
-                     assign(t9,
-                            binop(Iop_Or32,
-                                  mkexpr(t11),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t10),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_32to8, mkexpr(t0)),
-                                         unop(Iop_32to8, mkexpr(t3))),
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_32to8, mkexpr(t6)),
-                                         unop(Iop_32to8, mkexpr(t9)))));
-                     break;
-                  }
-                  case 0x5: {  /* SHRA_R.QB */
-                     DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I8);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I8);
-
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        assign(t0, unop(Iop_8Sto32,
-                                        unop(Iop_16to8,
-                                             unop(Iop_32to16, getIReg(rt)))));
-                        assign(t1, unop(Iop_32to8,
-                                        binop(Iop_Sar32,
-                                              binop(Iop_Add32,
-                                                    mkexpr(t0),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(rs-1))),
-                                              mkU8(rs))));
-
-                        assign(t2, unop(Iop_8Sto32,
-                                        unop(Iop_16HIto8,
-                                             unop(Iop_32to16, getIReg(rt)))));
-                        assign(t3, unop(Iop_32to8,
-                                        binop(Iop_Sar32,
-                                              binop(Iop_Add32,
-                                                    mkexpr(t2),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(rs-1))),
-                                              mkU8(rs))));
-
-                        assign(t4, unop(Iop_8Sto32,
-                                        unop(Iop_16to8,
-                                             unop(Iop_32HIto16, getIReg(rt)))));
-                        assign(t5, unop(Iop_32to8,
-                                        binop(Iop_Sar32,
-                                              binop(Iop_Add32,
-                                                    mkexpr(t4),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(rs-1))),
-                                              mkU8(rs))));
-
-                        assign(t6, unop(Iop_8Sto32,
-                                        unop(Iop_16HIto8,
-                                             unop(Iop_32HIto16, getIReg(rt)))));
-                        assign(t7, unop(Iop_32to8,
-                                        binop(Iop_Sar32,
-                                              binop(Iop_Add32,
-                                                    mkexpr(t6),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(rs-1))),
-                                              mkU8(rs))));
-                        putIReg(rd, binop(Iop_16HLto32,
-                                         binop(Iop_8HLto16,
-                                               mkexpr(t7), mkexpr(t5)),
-                                         binop(Iop_8HLto16,
-                                               mkexpr(t3), mkexpr(t1))));
-                     }
-                     break;
-                  }
-                  case 0x6: {  /* SHRAV.QB */
-                     DIP("shrav.qb r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
+      case 0x01: { /* SAT_U.df */
+         switch (df) {
+            case 0x00: { /* SAT_U.B */
+               DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
 
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
+               if (m == 7) {
+                  putWReg(wd, getWReg(ws));
+               } else {
+                  t1 = newTemp(Ity_V128);
+                  assign(t1,
+                         binop(Iop_CmpEQ8x16,
+                               binop(Iop_ShrN8x16,
+                                     getWReg(ws),
+                                     mkU8(m + 1)),
+                               binop(Iop_64HLtoV128,
+                                     mkU64(0), mkU64(0))));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                binop(Iop_ShrN8x16,
+                                      unop(Iop_NotV128,
+                                           mkexpr(t1)),
+                                      mkU8(7 - m))));
+               }
 
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
+               break;
+            }
 
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
+            case 0x01: { /* SAT_U.H */
+               DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
 
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
+               if (m == 15) {
+                  putWReg(wd, getWReg(ws));
+               } else {
+                  t1 = newTemp(Ity_V128);
+                  assign(t1,
+                         binop(Iop_CmpEQ16x8,
+                               binop(Iop_ShrN16x8,
+                                     getWReg(ws),
+                                     mkU8(m + 1)),
+                               binop(Iop_64HLtoV128,
+                                     mkU64(0), mkU64(0))));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                binop(Iop_ShrN16x8,
+                                      unop(Iop_NotV128,
+                                           mkexpr(t1)),
+                                      mkU8(15 - m))));
+               }
 
-                     /* ========== GPR[rt]_31..24 ========== */
-                     assign(t1,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16HIto8,
-                                      unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t2,
-                            binop(Iop_Shr32,
-                                  mkexpr(t1),
-                                  unop(Iop_32to8, binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x7)))));
-                     /* tempD_7..0 */
-                     assign(t0,
-                            binop(Iop_Or32,
-                                  mkexpr(t2),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t1),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8,
-                                              mkU8(0x8),
-                                              unop(Iop_32to8, binop(Iop_And32,
-                                                                    getIReg(rs),
-                                                                    mkU32(0x7)))
-                                              ))));
-
-                     /* ========== GPR[rt]_23..16 ========== */
-                     assign(t4,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16to8,
-                                      unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t5,
-                            binop(Iop_Shr32,
-                                  mkexpr(t4),
-                                  unop(Iop_32to8, binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x7)))));
-                     /* tempC_7..0 */
-                     assign(t3,
-                            binop(Iop_Or32,
-                                  mkexpr(t5),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t4),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8,
-                                              mkU8(0x8),
-                                              unop(Iop_32to8, binop(Iop_And32,
-                                                                    getIReg(rs),
-                                                                    mkU32(0x7)))
-                                              ))));
-
-                     /* ========== GPR[rt]_15..8 ========== */
-                     assign(t7,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16HIto8,
-                                      unop(Iop_32to16, getIReg(rt)))));
-                     assign(t8,
-                            binop(Iop_Shr32,
-                                  mkexpr(t7),
-                                  unop(Iop_32to8, binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x7)))));
-                     /* tempB_7..0 */
-                     assign(t6,
-                            binop(Iop_Or32,
-                                  mkexpr(t8),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t7),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8,
-                                              mkU8(0x8),
-                                              unop(Iop_32to8, binop(Iop_And32,
-                                                                    getIReg(rs),
-                                                                    mkU32(0x7)))
-                                              ))));
-
-                     /* ========== GPR[rt]_7..0 ========== */
-                     assign(t10,
-                            unop(Iop_8Uto32,
-                                 unop(Iop_16to8,
-                                      unop(Iop_32to16, getIReg(rt)))));
-                     assign(t11,
-                            binop(Iop_Shr32,
-                                  mkexpr(t10),
-                                  unop(Iop_32to8, binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x7)))));
-                     /* tempB_7..0 */
-                     assign(t9,
-                            binop(Iop_Or32,
-                                  mkexpr(t11),
-                                  binop(Iop_Shl32,
-                                        IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                         binop(Iop_And32,
-                                                               mkexpr(t10),
-                                                               mkU32(0x00000080)
-                                                              ),
-                                                         mkU32(0x00000080)),
-                                                   mkU32(0xFFFFFFFF),
-                                                   mkU32(0x00000000)),
-                                        binop(Iop_Sub8,
-                                              mkU8(0x8),
-                                              unop(Iop_32to8, binop(Iop_And32,
-                                                                    getIReg(rs),
-                                                                    mkU32(0x7)))
-                                              ))));
-
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_32to8,
-                                              IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                               binop(Iop_And32,
-                                                                     mkU32(rs),
-                                                                     mkU32(0x7)
-                                                                    ),
-                                                               mkU32(0x0)),
-                                                         mkexpr(t1),
-                                                         mkexpr(t0))),
-                                         unop(Iop_32to8,
-                                              IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                               binop(Iop_And32,
-                                                                     mkU32(rs),
-                                                                     mkU32(0x7)
-                                                                    ),
-                                                               mkU32(0x0)),
-                                                         mkexpr(t2),
-                                                         mkexpr(t3)))),
-                                   binop(Iop_8HLto16,
-                                         unop(Iop_32to8,
-                                              IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                               binop(Iop_And32,
-                                                                     mkU32(rs),
-                                                                     mkU32(0x7)
-                                                                    ),
-                                                               mkU32(0x0)),
-                                                         mkexpr(t5),
-                                                         mkexpr(t6))),
-                                         unop(Iop_32to8,
-                                              IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                               binop(Iop_And32,
-                                                                     mkU32(rs),
-                                                                     mkU32(0x7)
-                                                                    ),
-                                                               mkU32(0x0)),
-                                                         mkexpr(t8),
-                                                         mkexpr(t9))))));
-                     break;
-                  }
-                  case 0x7: {  /* SHRAV_R.QB */
-                     DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I8);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I8);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I8);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I8);
-                     t8 = newTemp(Ity_I8);
-                     t9 = newTemp(Ity_I32);
-
-                     assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
-                     assign(t8, unop(Iop_32to8,
-                                     binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
-                     assign(t0, unop(Iop_8Sto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t1, unop(Iop_32to8,
-                                     binop(Iop_Sar32,
-                                           binop(Iop_Add32,
-                                                 mkexpr(t0),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkexpr(t8))),
-                                           unop(Iop_32to8,
-                                                mkexpr(t9)))));
-
-                     assign(t2, unop(Iop_8Sto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t3, unop(Iop_32to8,
-                                     binop(Iop_Sar32,
-                                           binop(Iop_Add32,
-                                                 mkexpr(t2),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkexpr(t8))),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-
-                     assign(t4, unop(Iop_8Sto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t5, unop(Iop_32to8,
-                                     binop(Iop_Sar32,
-                                           binop(Iop_Add32,
-                                                 mkexpr(t4),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkexpr(t8))),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-
-                     assign(t6, unop(Iop_8Sto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t7, unop(Iop_32to8,
-                                     binop(Iop_Sar32,
-                                           binop(Iop_Add32,
-                                                 mkexpr(t6),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkexpr(t8))),
-                                           unop(Iop_32to8, mkexpr(t9)))));
-                     putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  mkexpr(t9),
-                                                  mkU32(0x0)),
-                                            getIReg(rt),
-                                            binop(Iop_16HLto32,
-                                                  binop(Iop_8HLto16,
-                                                        mkexpr(t7),
-                                                        mkexpr(t5)),
-                                                  binop(Iop_8HLto16,
-                                                        mkexpr(t3),
-                                                        mkexpr(t1)))));
-                     break;
-                  }
-                  case 0x8: {  /* SHLL.PH */
-                     DIP("shll.ph r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
+               break;
+            }
 
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        /* Shift lower 16 bits. */
-                        assign(t0, binop(Iop_Shl32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32to16, getIReg(rt))),
-                                         mkU8(rs)));
-
-                        assign(t1, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                               binop(Iop_Sar32,
-                                                     mkexpr(t0),
-                                                     mkU8(16)),
-                                               mkU32(0))));
-                        assign(t2, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                              binop(Iop_Sar32,
-                                                    mkexpr(t0),
-                                                    mkU8(16)),
-                                              mkU32(0xffffffff))));
-                        assign(t3, binop(Iop_And32,
-                                         mkexpr(t1),
-                                         mkexpr(t2)));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t3),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       binop(Iop_And32,
-                                                             getIReg(rt),
-                                                             mkU32(0x00008000)),
-                                                       binop(Iop_And32,
-                                                             mkexpr(t0),
-                                                             mkU32(0x00008000))
-                                                      ),
-                                                 getDSPControl(),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000))));
-                        /* Shift higher 16 bits. */
-                        assign(t4, binop(Iop_Shl32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32HIto16, getIReg(rt))),
-                                         mkU8(rs)));
-
-                        assign(t5, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                               binop(Iop_Sar32,
-                                                     mkexpr(t4),
-                                                     mkU8(16)),
-                                               mkU32(0))));
-                        assign(t6, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                              binop(Iop_Sar32,
-                                                    mkexpr(t4),
-                                                    mkU8(16)),
-                                              mkU32(0xffffffff))));
-                        assign(t7, binop(Iop_And32,
-                                         mkexpr(t5),
-                                         mkexpr(t6)));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t7),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t7),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       binop(Iop_And32,
-                                                             getIReg(rt),
-                                                             mkU32(0x80000000)),
-                                                       binop(Iop_Shl32,
-                                                             binop(Iop_And32,
-                                                                   mkexpr(t4),
-                                                                   mkU32(0x00008000)),
-                                                             mkU8(16))
-                                                      ),
-                                                 getDSPControl(),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000))));
-                        putIReg(rd, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, mkexpr(t4)),
-                                          unop(Iop_32to16, mkexpr(t0))));
-                     }
-                     break;
-                  }
-                  case 0x9: {  /* SHRA.PH */
-                     DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        assign(t0, binop(Iop_Sar32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32to16, getIReg(rt))),
-                                         mkU8(rs)));
-                        assign(t1, binop(Iop_Sar32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32HIto16, getIReg(rt))),
-                                         mkU8(rs)));
-                        putIReg(rd, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, mkexpr(t1)),
-                                          unop(Iop_32to16, mkexpr(t0))));
-                     }
-                     break;
-                  }
-                  case 0xA: {  /* SHLLV.PH */
-                     DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-
-                     /* Shift lower 16 bits. */
-                     assign(t2, binop(Iop_Shl32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x00000000)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0xffffffff)));
-                     assign(t10, binop(Iop_And32,
-                                       unop(Iop_1Sto32, mkexpr(t3)),
-                                       unop(Iop_1Sto32, mkexpr(t4))));
-                     assign(t5, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0x00008000)),
-                                      mkU8(15)));
-                     assign(t12, binop(Iop_CmpEQ32,
-                                       mkexpr(t5),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   mkexpr(t2),
-                                                   mkU32(0x00008000)),
-                                             mkU8(15))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t10),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              IRExpr_ITE(mkexpr(t12),
-                                                         getDSPControl(),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x400000)))
-                                             ));
-                     /* Shift higher 16 bits. */
-                     assign(t6, binop(Iop_Shl32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     assign(t7, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t6))),
-                                      mkU32(0x00000000)));
-                     assign(t8, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t6))),
-                                      mkU32(0xffffffff)));
-                     assign(t11, binop(Iop_And32,
-                                       unop(Iop_1Sto32, mkexpr(t7)),
-                                       unop(Iop_1Sto32, mkexpr(t8))));
-
-                     assign(t9, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0x80000000)),
-                                      mkU8(31)));
-                     assign(t13, binop(Iop_CmpEQ32,
-                                       mkexpr(t9),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   mkexpr(t6),
-                                                   mkU32(0x00008000)),
-                                             mkU8(15))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t11),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              IRExpr_ITE(mkexpr(t13),
-                                                         getDSPControl(),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x400000)))
-                                             ));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t6)),
-                                       unop(Iop_32to16, mkexpr(t2))));
-                     break;
-                  }
-                  case 0xB: {  /* SHRAV.PH */
-                     DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-                     assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-                     assign(t2, binop(Iop_Sar32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-                     assign(t3, binop(Iop_Sar32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-                     putIReg(rd,
-                             binop(Iop_16HLto32,
-                                   IRExpr_ITE(mkexpr(t1),
-                                              unop(Iop_32HIto16, getIReg(rt)),
-                                              unop(Iop_32to16, mkexpr(t3))),
-                                   IRExpr_ITE(mkexpr(t1),
-                                              unop(Iop_32to16, getIReg(rt)),
-                                              unop(Iop_32to16, mkexpr(t2)))));
-                     break;
-                  }
-                  case 0xC: {  /* SHLL_S.PH */
-                     DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
-                     t12 = newTemp(Ity_I32);
-                     t13 = newTemp(Ity_I32);
-                     t14 = newTemp(Ity_I32);
-
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        /* Shift lower 16 bits. */
-                        assign(t0, binop(Iop_Shl32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32to16, getIReg(rt))),
-                                         mkU8(rs)));
-
-                        assign(t1, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                               binop(Iop_Sar32,
-                                                     mkexpr(t0),
-                                                     mkU8(16)),
-                                               mkU32(0))));
-                        assign(t2, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                              binop(Iop_Sar32,
-                                                    mkexpr(t0),
-                                                    mkU8(16)),
-                                              mkU32(0xffffffff))));
-                        assign(t3, binop(Iop_And32,
-                                         mkexpr(t1),
-                                         mkexpr(t2)));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t3),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       binop(Iop_And32,
-                                                             getIReg(rt),
-                                                             mkU32(0x00008000)),
-                                                       binop(Iop_And32,
-                                                             mkexpr(t0),
-                                                             mkU32(0x00008000))
-                                                      ),
-                                                 getDSPControl(),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000))));
-                        assign(t8,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                mkexpr(t3),
-                                                mkU32(0x1)),
-                                          IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                           binop(Iop_And32,
-                                                                 getIReg(rt),
-                                                                 mkU32(0x8000)),
-                                                           mkU32(0)),
-                                                     mkU32(0x00007fff),
-                                                     mkU32(0x00008000)),
-                                          binop(Iop_And32,
-                                                mkexpr(t0),
-                                                mkU32(0x0000ffff))));
-                        assign(t10,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                binop(Iop_And32,
-                                                      getIReg(rt),
-                                                      mkU32(0x00008000)),
-                                                binop(Iop_And32,
-                                                      mkexpr(t0),
-                                                      mkU32(0x00008000))),
-                                          mkexpr(t8),
-                                          IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                           binop(Iop_And32,
-                                                                 getIReg(rt),
-                                                                 mkU32(0x8000)),
-                                                           mkU32(0)),
-                                                     mkU32(0x00007fff),
-                                                     mkU32(0x00008000))));
-                        /* Shift higher 16 bits. */
-                        assign(t4, binop(Iop_Shl32,
-                                         unop(Iop_16Sto32,
-                                              unop(Iop_32HIto16, getIReg(rt))),
-                                         mkU8(rs)));
-
-                        assign(t5, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                               binop(Iop_Sar32,
-                                                     mkexpr(t4),
-                                                     mkU8(16)),
-                                               mkU32(0))));
-                        assign(t6, unop(Iop_1Uto32,
-                                        binop(Iop_CmpNE32,
-                                              binop(Iop_Sar32,
-                                                    mkexpr(t4),
-                                                    mkU8(16)),
-                                              mkU32(0xffffffff))));
-                        assign(t7, binop(Iop_And32,
-                                         mkexpr(t5),
-                                         mkexpr(t6)));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t7),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       mkexpr(t7),
-                                                       mkU32(0x1)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000)),
-                                                 getDSPControl()));
-                        assign(t12, binop(Iop_Shl32,
-                                          binop(Iop_And32,
-                                                mkexpr(t4),
-                                                mkU32(0x8000)),
-                                          mkU8(16)));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       binop(Iop_And32,
-                                                             getIReg(rt),
-                                                             mkU32(0x80000000)),
-                                                       mkexpr(t12)),
-                                                 getDSPControl(),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000))));
-                        assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                     binop(Iop_And32,
-                                                           getIReg(rt),
-                                                           mkU32(0x80000000)),
-                                                     mkU32(0)),
-                                               mkU32(0x7fff0000),
-                                               mkU32(0x80000000)));
-                        assign(t9,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                mkexpr(t7),
-                                                mkU32(0x1)),
-                                          mkexpr(t13),
-                                          binop(Iop_Shl32,
-                                                binop(Iop_And32,
-                                                      mkexpr(t4),
-                                                      mkU32(0x0000ffff)),
-                                                mkU8(16))));
-                        assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                     binop(Iop_And32,
-                                                           getIReg(rt),
-                                                           mkU32(0x80000000)),
-                                                     mkU32(0)),
-                                               mkU32(0x7fff0000),
-                                               mkU32(0x80000000)));
-                        assign(t11,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                binop(Iop_And32,
-                                                      getIReg(rt),
-                                                      mkU32(0x80000000)),
-                                                binop(Iop_Shl32,
-                                                      binop(Iop_And32,
-                                                            mkexpr(t4),
-                                                            mkU32(0x00008000)),
-                                                      mkU8(16))),
-                                          mkexpr(t9),
-                                          mkexpr(t14)));
-                        putIReg(rd, binop(Iop_Or32,
-                                          mkexpr(t10),
-                                          mkexpr(t11)));
-                     }
-                     break;
-                  }
-                  case 0xD: {  /* SHRA_R.PH */
-                     DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        assign(t0, binop(Iop_Sar32,
-                                         binop(Iop_Add32,
-                                               unop(Iop_16Sto32,
-                                                    unop(Iop_32to16,
-                                                         getIReg(rt))),
-                                               binop(Iop_Shl32,
-                                                     mkU32(0x1),
-                                                     mkU8(rs-1))),
-                                         mkU8(rs)));
-                        assign(t1, binop(Iop_Sar32,
-                                         binop(Iop_Add32,
-                                               unop(Iop_16Sto32,
-                                                    unop(Iop_32HIto16,
-                                                         getIReg(rt))),
-                                               binop(Iop_Shl32,
-                                                     mkU32(0x1),
-                                                     mkU8(rs-1))),
-                                         mkU8(rs)));
-                        putIReg(rd, binop(Iop_16HLto32,
-                                          unop(Iop_32to16, mkexpr(t1)),
-                                          unop(Iop_32to16, mkexpr(t0))));
-                     }
-                     break;
-                  }
-                  case 0xE: {  /* SHLLV_S.PH */
-                     DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I16);
-                     t15 = newTemp(Ity_I16);
-                     t16 = newTemp(Ity_I16);
-                     t17 = newTemp(Ity_I16);
-
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-
-                     /* Shift lower 16 bits. */
-                     assign(t2, binop(Iop_Shl32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     assign(t3, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0x00000000)));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t2))),
-                                      mkU32(0xffffffff)));
-                     assign(t10, binop(Iop_And32,
-                                       unop(Iop_1Sto32, mkexpr(t3)),
-                                       unop(Iop_1Sto32, mkexpr(t4))));
-                     assign(t5, binop(Iop_Shr32,
-                                       binop(Iop_And32,
-                                             getIReg(rt),
-                                             mkU32(0x00008000)),
-                                       mkU8(15)));
-                     assign(t12, binop(Iop_CmpEQ32,
-                                       mkexpr(t5),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   mkexpr(t2),
-                                                   mkU32(0x00008000)),
-                                             mkU8(15))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t10),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              IRExpr_ITE(mkexpr(t12),
-                                                         getDSPControl(),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x400000)))
-                                             ));
-                     assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t5),
-                                                  mkU32(0x0)),
-                                            mkU16(0x8000),
-                                            mkU16(0x7fff)));
-                     assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t10),
-                                                  mkU32(0x0)),
-                                            mkexpr(t14),
-                                            IRExpr_ITE(mkexpr(t12),
-                                                       unop(Iop_32to16,
-                                                            mkexpr(t2)),
-                                                       mkexpr(t14))));
-                     /* Shift higher 16 bits. */
-                     assign(t6, binop(Iop_Shl32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     assign(t7, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t6))),
-                                      mkU32(0x00000000)));
-                     assign(t8, binop(Iop_CmpNE32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, mkexpr(t6))),
-                                      mkU32(0xffffffff)));
-                     assign(t11, binop(Iop_And32,
-                                       unop(Iop_1Sto32, mkexpr(t7)),
-                                       unop(Iop_1Sto32, mkexpr(t8))));
-
-                     assign(t9, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0x80000000)),
-                                      mkU8(31)));
-                     assign(t13, binop(Iop_CmpEQ32,
-                                       mkexpr(t9),
-                                       binop(Iop_Shr32,
-                                             binop(Iop_And32,
-                                                   mkexpr(t6),
-                                                   mkU32(0x00008000)),
-                                             mkU8(15))));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t11),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              IRExpr_ITE(mkexpr(t13),
-                                                         getDSPControl(),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x400000)))
-                                             ));
-
-                     assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t9),
-                                                  mkU32(0x0)),
-                                            mkU16(0x8000),
-                                            mkU16(0x7fff)));
-                     assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t11),
-                                                  mkU32(0x0)),
-                                            mkexpr(t16),
-                                            IRExpr_ITE(mkexpr(t13),
-                                                       unop(Iop_32to16,
-                                                            mkexpr(t6)),
-                                                       mkexpr(t16))));
-
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
-                     break;
-                  }
-                  case 0xF: {  /* SHRAV_R.PH */
-                     DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-                     assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-                     assign(t2, unop(Iop_32to8,
-                                     binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
-
-                     assign(t3, binop(Iop_Sar32,
-                                      binop(Iop_Add32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16, getIReg(rt))),
-                                            binop(Iop_Shl32,
-                                                  mkU32(0x1),
-                                                  mkexpr(t2))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-                     assign(t4, binop(Iop_Sar32,
-                                      binop(Iop_Add32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt))),
-                                            binop(Iop_Shl32,
-                                                  mkU32(0x1),
-                                                  mkexpr(t2))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       IRExpr_ITE(mkexpr(t1),
-                                                  unop(Iop_32HIto16,
-                                                       getIReg(rt)),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t4))),
-                                       IRExpr_ITE(mkexpr(t1),
-                                                  unop(Iop_32to16, getIReg(rt)),
-                                                  unop(Iop_32to16,
-                                                       mkexpr(t3)))));
-                     break;
-                  }
-                  case 0x14: {  /* SHLL_S.W */
-                     DIP("shll_s.w r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
+            case 0x02: { /* SAT_U.W */
+               DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
 
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        /* t0-bits that will be discarded, sign extended to
-                           32bits. */
-                        assign(t0, binop(Iop_Sar32,
-                                         binop(Iop_And32,
-                                               getIReg(rt),
-                                               binop(Iop_Sar32,
-                                                     mkU32(0x80000000),
-                                                     mkU8(rs-1))),
-                                         mkU8(32-rs)));
-
-                        assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_And32,
-                                                          getIReg(rt),
-                                                          mkU32(0x80000000)),
-                                                    mkU32(0x0)),
-                                              mkU32(0x7fffffff),
-                                              mkU32(0x80000000)));
-
-                        assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
-                        assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_And32,
-                                                          getIReg(rt),
-                                                          mkU32(0x80000000)),
-                                                    binop(Iop_And32,
-                                                          mkexpr(t2),
-                                                          mkU32(0x80000000))),
-                                              mkexpr(t2),
-                                              mkexpr(t1)));
-
-                        assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t0),
-                                                    mkU32(0x0)),
-                                              IRExpr_ITE(binop(Iop_CmpNE32,
-                                                               mkexpr(t0),
-                                                               mkU32(0xffffffff)
-                                                              ),
-                                                         mkexpr(t1),
-                                                         mkexpr(t3)),
-                                              mkexpr(t3)));
-                        assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t0),
-                                                    mkU32(0xffffffff)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x0)),
-                                                 mkexpr(t5),
-                                                 getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                       binop(Iop_And32,
-                                                             getIReg(rt),
-                                                             mkU32(0x80000000)),
-                                                       binop(Iop_And32,
-                                                             mkexpr(t2),
-                                                             mkU32(0x80000000))
-                                                            ),
-                                                 getDSPControl(),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x400000))));
-                        putIReg(rd, mkexpr(t4));
-                     }
-                     break;
-                  }
-                  case 0x15: {  /* SHRA_R.W */
-                     DIP("shra_r.w r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     if (0 == rs) {
-                        putIReg(rd, getIReg(rt));
-                     } else {
-                        putIReg(rd, binop(Iop_Add32,
-                                          binop(Iop_Sar32,
-                                                getIReg(rt), mkU8(rs)),
-                                          binop(Iop_Shr32,
-                                                binop(Iop_And32,
-                                                      getIReg(rt),
-                                                      binop(Iop_Shl32,
-                                                            mkU32(0x1),
-                                                            mkU8(rs-1))),
-                                                mkU8(rs-1))));
-                     }
-                     break;
-                  }
-                  case 0x16: {  /* SHLLV_S.W */
-                     DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I1);
-                     t5 = newTemp(Ity_I1);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I32);
-
-                     /* Check if shift amount is zero. */
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
-                     assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-
-                     /* t2 = sign of the input value. */
-                     assign(t2, binop(Iop_Shr32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0x80000000)),
-                                      mkU8(31)));
-                     /* Shift left input value and check for overflow. */
-                     assign(t3, binop(Iop_Shl64,
-                                      unop(Iop_32Sto64, getIReg(rt)),
-                                      unop(Iop_32to8, mkexpr(t0))));
-                     assign(t4, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32, mkexpr(t3)),
-                                      mkU32(0x00000000)));
-                     assign(t5, binop(Iop_CmpNE32,
-                                      unop(Iop_64HIto32, mkexpr(t3)),
-                                      mkU32(0xffffffff)));
-                     assign(t6, binop(Iop_And32,
-                                      unop(Iop_1Uto32, mkexpr(t4)),
-                                      unop(Iop_1Uto32, mkexpr(t5))));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  getIReg(rt),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t3)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31))));
-
-                     putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
-                                                   binop(Iop_Or32,
-                                                         getDSPControl(),
-                                                         mkU32(0x400000)),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         getDSPControl(),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x400000)))
-                                             ));
-
-                     assign(t8, IRExpr_ITE(unop(Iop_32to1,
-                                                mkexpr(t2)),
-                                           mkU32(0x80000000),
-                                           mkU32(0x7fffffff)));
-                     putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
-                                            IRExpr_ITE(unop(Iop_32to1,
-                                                            mkexpr(t2)),
-                                                       mkU32(0x80000000),
-                                                       mkU32(0x7fffffff)),
-                                            IRExpr_ITE(mkexpr(t7),
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t3)),
-                                                       mkexpr(t8))));
-                     break;
-                  }
-                  case 0x17: {  /* SHRAV_R.W */
-                     DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I32);
-
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
-                     assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-                     assign(t2, unop(Iop_32to8,
-                                     binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
-
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            getIReg(rt),
-                                            binop(Iop_Sar32,
-                                                  binop(Iop_Add32,
-                                                        binop(Iop_Sar32,
-                                                              getIReg(rt),
-                                                              mkexpr(t2)),
-                                                        mkU32(0x1)),
-                                                  mkU8(1))));
-                     break;
-                  }
-                  case 0x19: {  /* SHRL.PH */
-                     DIP("shrl.ph r%u, r%u, %u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     assign(t0, binop(Iop_Shr32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU8(rs)));
-                     assign(t1, binop(Iop_Shr32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU8(rs)));
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       unop(Iop_32to16, mkexpr(t1)),
-                                       unop(Iop_32to16, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x1B: {  /* SHRLV.PH */
-                     DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I16);
-                     t5 = newTemp(Ity_I16);
-
-                     /* Get shift amount from lower 5 bits of rs
-                        and check if it is zero. */
-                     assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-                     assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-
-                     assign(t2, binop(Iop_Shr32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-                     assign(t3, binop(Iop_Shr32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      unop(Iop_32to8, mkexpr(t0))));
-
-                     assign(t4, IRExpr_ITE(mkexpr(t1),
-                                           unop(Iop_32HIto16, getIReg(rt)),
-                                           unop(Iop_32to16, mkexpr(t3))));
-                     assign(t5, IRExpr_ITE(mkexpr(t1),
-                                           unop(Iop_32to16, getIReg(rt)),
-                                           unop(Iop_32to16, mkexpr(t2))));
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
-                     break;
-                  }
-                  default:
-                     return -1;
+               if (m == 31) {
+                  putWReg(wd, getWReg(ws));
+               } else {
+                  t1 = newTemp(Ity_V128);
+                  assign(t1,
+                         binop(Iop_CmpEQ32x4,
+                               binop(Iop_ShrN32x4,
+                                     getWReg(ws),
+                                     mkU8(m + 1)),
+                               binop(Iop_64HLtoV128,
+                                     mkU64(0), mkU64(0))));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1), \
+                                      getWReg(ws)),
+                                binop(Iop_ShrN32x4,
+                                      unop(Iop_NotV128,
+                                           mkexpr(t1)),
+                                      mkU8(31 - m))));
                }
-               break;  /* end of SHLL.QB */
+
+               break;
             }
-            case 0x18: {  /* ADDUH.QB/MUL.PH */
-               switch(sa) {
-                  case 0x00: {  /* ADDUH.QB */
-                     DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
 
-                     assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));
+            case 0x03: { /* SAT_U.D */
+               DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
 
-                     putIReg(rd, mkexpr(t0));
-                     break;
-                  }
-                  case 0x1: {  /* SUBUH.QB */
-                     DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
+               if (m == 63) {
+                  putWReg(wd, getWReg(ws));
+               } else {
+                  t1 = newTemp(Ity_V128);
+                  assign(t1,
+                         binop(Iop_CmpEQ64x2,
+                               binop(Iop_ShrN64x2,
+                                     getWReg(ws),
+                                     mkU8(m + 1)),
+                               binop(Iop_64HLtoV128,
+                                     mkU64(0), mkU64(0))));
+                  putWReg(wd,
+                          binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                binop(Iop_ShrN64x2,
+                                      unop(Iop_NotV128,
+                                           mkexpr(t1)),
+                                      mkU8(63 - m))));
+               }
 
-                     assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));
+               break;
+            }
+         }
 
-                     putIReg(rd, mkexpr(t0));
-                     break;
-                  }
-                  case 0x02: {  /* ADDUH_R.QB */
-                     DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I8);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I8);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I8);
-                     t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I8);
-
-                     /* Extract input bytes, add values, add 1 and half the
-                        result. */
-                     assign(t0, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rs)))));
-                     assign(t1, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t2, unop(Iop_16to8,
-                                     unop(Iop_32to16,
-                                          binop(Iop_Shr32,
-                                                binop(Iop_Add32,
-                                                      binop(Iop_Add32,
-                                                            mkexpr(t0),
-                                                            mkexpr(t1)),
-                                                      mkU32(0x00000001)),
-                                                mkU8(0x01)))));
-
-                     assign(t3, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rs)))));
-                     assign(t4, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t5, unop(Iop_16to8,
-                                     unop(Iop_32to16,
-                                          binop(Iop_Shr32,
-                                                binop(Iop_Add32,
-                                                      binop(Iop_Add32,
-                                                            mkexpr(t3),
-                                                            mkexpr(t4)),
-                                                      mkU32(0x00000001)),
-                                                mkU8(0x01)))));
-
-                     assign(t6, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rs)))));
-                     assign(t7, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t8, unop(Iop_16to8,
-                                     unop(Iop_32to16,
-                                          binop(Iop_Shr32,
-                                                binop(Iop_Add32,
-                                                      binop(Iop_Add32,
-                                                            mkexpr(t7),
-                                                            mkexpr(t6)),
-                                                      mkU32(0x00000001)),
-                                                mkU8(0x01)))));
-
-                     assign(t9, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16, getIReg(rs)))));
-                     assign(t10, unop(Iop_8Uto32,
-                                      unop(Iop_16HIto8,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t11, unop(Iop_16to8,
-                                      unop(Iop_32to16,
-                                           binop(Iop_Shr32,
-                                                 binop(Iop_Add32,
-                                                       binop(Iop_Add32,
-                                                             mkexpr(t9),
-                                                             mkexpr(t10)),
-                                                       mkU32(0x00000001)),
-                                                 mkU8(0x01)))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t11), mkexpr(t8)),
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t5), mkexpr(t2))));
-                     break;
-                  }
-                  case 0x3: {  /* SUBUH_R.QB */
-                     DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
-                     t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I8);
-                     t10 = newTemp(Ity_I8);
-                     t11 = newTemp(Ity_I8);
-                     t12 = newTemp(Ity_I8);
-
-                     /* Extract each byte of rs and rt. */
-                     assign(t1, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rs)))));
-                     assign(t2, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rs)))));
-                     assign(t3, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rs)))));
-                     assign(t4, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16, getIReg(rs)))));
+         break;
+      }
 
-                     assign(t5, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t6, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16, getIReg(rt)))));
-                     assign(t7, unop(Iop_8Uto32,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t8, unop(Iop_8Uto32,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16, getIReg(rt)))));
-
-                     /* Add 1 to each resulting byte and half the results. */
-                     assign(t9, unop(Iop_16to8,
-                                     unop(Iop_32to16,
-                                          binop(Iop_Shr32,
-                                                binop(Iop_Add32,
-                                                      binop(Iop_Sub32,
-                                                            mkexpr(t1),
-                                                            mkexpr(t5)),
-                                                      mkU32(0x00000001)),
-                                                mkU8(0x01)))));
-                     assign(t10, unop(Iop_16to8,
-                                      unop(Iop_32to16,
-                                           binop(Iop_Shr32,
-                                                 binop(Iop_Add32,
-                                                       binop(Iop_Sub32,
-                                                             mkexpr(t2),
-                                                             mkexpr(t6)),
-                                                       mkU32(0x00000001)),
-                                                 mkU8(0x01)))));
-                     assign(t11, unop(Iop_16to8,
-                                      unop(Iop_32to16,
-                                            binop(Iop_Shr32,
-                                                  binop(Iop_Add32,
-                                                        binop(Iop_Sub32,
-                                                              mkexpr(t3),
-                                                              mkexpr(t7)),
-                                                        mkU32(0x00000001)),
-                                                  mkU8(0x01)))));
-                     assign(t12, unop(Iop_16to8,
-                                      unop(Iop_32to16,
-                                           binop(Iop_Shr32,
-                                                 binop(Iop_Add32,
-                                                       binop(Iop_Sub32,
-                                                             mkexpr(t4),
-                                                             mkexpr(t8)),
-                                                       mkU32(0x00000001)),
-                                                 mkU8(0x01)))));
-
-                     putIReg(rd, binop(Iop_16HLto32,
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t12), mkexpr(t11)),
-                                       binop(Iop_8HLto16,
-                                             mkexpr(t10), mkexpr(t9))));
-                     break;
-                  }
-                  case 0x8: {  /* ADDQH.PH */
-                     DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I16);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I16);
-
-                     /* Add lower halfs of rs and rt
-                        and right shift the result by 1. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-                     assign(t1, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 mkexpr(t0),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
-                     /* Add higher halfs of rs and rt
-                        and right shift the result by 1. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t3, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 mkexpr(t2),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
-                     break;
-                  }
-                  case 0x9: {  /* SUBQH.PH */
-                     DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
+      case 0x02: { /* SRARI.df */
+         switch (df) {
+            case 0x00: { /* SRARI.B */
+               DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_SarN8x16,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN8x16,
+                            binop(Iop_ShlN8x16,
+                                  getWReg(ws),
+                                  mkU8(8 - m)),
+                            mkU8(7)));
 
-                     putIReg(rd, binop(Iop_HSub16Sx2,
-                                       getIReg(rs), getIReg(rt)));
-                     break;
-                  }
-                  case 0xA: {/* ADDQH_R.PH */
-                     DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I16);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I16);
-
-                     /* Add lower halfs of rs and rt, add 1
-                        and right shift the result by 1. */
-                     assign(t0, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-                     assign(t1, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 binop(Iop_Add32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x1)),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
-                     /* Add higher halfs of rs and rt, add 1
-                        and right shift the result by 1. */
-                     assign(t2, binop(Iop_Add32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t3, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 binop(Iop_Add32,
-                                                       mkexpr(t2),
-                                                       mkU32(0x1)),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
+               if (m) putWReg(wd, binop(Iop_Add8x16,
+                                           mkexpr(t1),
+                                           mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
-                     break;
-                  }
-                  case 0xB: {  /* SUBQH_R.PH */
-                     DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I16);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I16);
-
-                     /* Sub lower halfs of rs and rt, add 1
-                        and right shift the result by 1. */
-                     assign(t0, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-                     assign(t1, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 binop(Iop_Add32,
-                                                       mkexpr(t0),
-                                                       mkU32(0x1)),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
-                     /* Sub higher halfs of rs and rt, add 1
-                        and right shift the result by 1. */
-                     assign(t2, binop(Iop_Sub32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt)))));
-                     assign(t3, unop(Iop_32to16,
-                                     binop(Iop_Shr32,
-                                           binop(Iop_And32,
-                                                 binop(Iop_Add32,
-                                                       mkexpr(t2),
-                                                       mkU32(0x1)),
-                                                 mkU32(0x0001fffe)),
-                                           mkU8(0x1))));
+               break;
+            }
 
-                     putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
-                     break;
-                  }
-                  case 0xC: {  /* MUL.PH */
-                     DIP("mul.ph r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-
-                     assign(t0,
-                            binop(Iop_Mul32,
-                                  unop(Iop_16Sto32,
-                                       unop(Iop_32HIto16, getIReg(rs))),
-                                  unop(Iop_16Sto32,
-                                       unop(Iop_32HIto16, getIReg(rt)))));
-                     /* DSP Control flag. */
-                     putDSPControl(IRExpr_ITE(unop(Iop_Not1,
-                                                   binop(Iop_CmpLE32S,
-                                                         mkexpr(t0),
-                                                         mkU32(0x7FFF))),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00200000)),
-                                              IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                               mkexpr(t0),
-                                                               mkU32(0xFFFF8000)
-                                                             ),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl())));
+            case 0x01: { /* SRARI.H */
+               DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_SarN16x8,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN16x8,
+                            binop(Iop_ShlN16x8,
+                                  getWReg(ws),
+                                  mkU8(16 - m)),
+                            mkU8(15)));
 
-                     assign(t1,
-                            binop(Iop_Mul32,
-                                  unop(Iop_16Sto32,
-                                       unop(Iop_32to16, getIReg(rs))),
-                                  unop(Iop_16Sto32,
-                                       unop(Iop_32to16, getIReg(rt)))));
-                     /* DSP Control flag. */
-                     putDSPControl(IRExpr_ITE(unop(Iop_Not1,
-                                                   binop(Iop_CmpLE32S,
-                                                         mkexpr(t1),
-                                                         mkU32(0x7FFF))),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00200000)),
-                                              IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                               mkexpr(t1),
-                                                               mkU32(0xFFFF8000)
-                                                              ),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl())));
-
-                     assign(t2, binop(Iop_16HLto32,
-                                      unop(Iop_32to16, mkexpr(t0)),
-                                      unop(Iop_32to16, mkexpr(t1))));
-                     putIReg(rd, mkexpr(t2));
-                     break;
-                  }
-                  case 0xE: {  /* MUL_S.PH */
-                     DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-
-                     /* t0 - signed intermediate result. */
-                     assign(t0,
-                           binop(Iop_Mul32,
-                                 unop(Iop_16Sto32,
-                                      unop(Iop_32HIto16, getIReg(rs))),
-                                 unop(Iop_16Sto32,
-                                      unop(Iop_32HIto16, getIReg(rt)))));
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add16x8,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     assign(t1,
-                            IRExpr_ITE(unop(Iop_Not1,
-                                            binop(Iop_CmpLE32S,
-                                                  mkexpr(t0),
-                                                  mkU32(0x7FFF))),
-                                       mkU32(0x00007FFF),
-                                       IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                        mkexpr(t0),
-                                                        mkU32(0xFFFF8000)),
-                                                  mkU32(0xFFFF8000),
-                                                  mkexpr(t0))));
-
-                     /* DSP Control flag. */
-                     putDSPControl(IRExpr_ITE(unop(Iop_Not1,
-                                                   binop(Iop_CmpLE32S,
-                                                         mkexpr(t0),
-                                                         mkU32(0x7FFF))),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00200000)),
-                                              IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                               mkexpr(t0),
-                                                               mkU32(0xFFFF8000)
-                                                              ),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl())));
-
-                     /* t2 - signed intermediate result. */
-                     assign(t2, binop(Iop_Mul32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt)))));
-
-                     assign(t3, IRExpr_ITE(unop(Iop_Not1,
-                                                binop(Iop_CmpLE32S,
-                                                      mkexpr(t2),
-                                                      mkU32(0x7FFF))),
-                                           mkU32(0x00007FFF),
-                                           IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                            mkexpr(t2),
-                                                            mkU32(0xFFFF8000)),
-                                                      mkU32(0xFFFF8000),
-                                                      mkexpr(t2))));
-
-                     /* DSP Control flag. */
-                     putDSPControl(IRExpr_ITE(unop(Iop_Not1,
-                                                   binop(Iop_CmpLE32S,
-                                                         mkexpr(t2),
-                                                         mkU32(0x7FFF))),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x00200000)),
-                                              IRExpr_ITE(binop(Iop_CmpLT32S,
-                                                               mkexpr(t2),
-                                                               mkU32(0xFFFF8000)
-                                                              ),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl())));
-
-                     assign(t4, binop(Iop_16HLto32,
-                                      unop(Iop_32to16, mkexpr(t1)),
-                                      unop(Iop_32to16, mkexpr(t3))));
-                     putIReg(rd, mkexpr(t4));
-                     break;
-                  }
-                  case 0x10: {  /* ADDQH.W */
-                     DIP("addqh.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
+               break;
+            }
 
-                     assign(t0, binop(Iop_Add64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-                     assign(t1, binop(Iop_And64,
-                                      mkexpr(t0),
-                                      mkU64(0x00000001fffffffeULL)));
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
-                     break;
-                  }
-                  case 0x11: {  /* SUBQH.W */
-                     DIP("subqh.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
+            case 0x02: { /* SRARI.W */
+               DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_SarN32x4,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN32x4,
+                            binop(Iop_ShlN32x4,
+                                  getWReg(ws),
+                                  mkU8(32 - m)),
+                            mkU8(31)));
 
-                     assign(t0, binop(Iop_Sub64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-                     assign(t1, binop(Iop_And64,
-                                      mkexpr(t0),
-                                      mkU64(0x00000001fffffffeULL)));
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
-                     break;
-                  }
-                  case 0x12: {  /* ADDQH_R.W */
-                     DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0, binop(Iop_Add64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-                     assign(t1, binop(Iop_Add64,
-                                      mkexpr(t0),
-                                      mkU64(0x0000000000000001ULL)));
-                     assign(t2, binop(Iop_And64,
-                                      mkexpr(t1),
-                                      mkU64(0x00000001fffffffeULL)));
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
-                     break;
-                  }
-                  case 0x13: {  /* SUBQH_R.W */
-                     DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0, binop(Iop_Sub64,
-                                      unop(Iop_32Sto64, getIReg(rs)),
-                                      unop(Iop_32Sto64, getIReg(rt))));
-                     assign(t1, binop(Iop_Add64,
-                                      mkexpr(t0),
-                                      mkU64(0x0000000000000001ULL)));
-                     assign(t2, binop(Iop_And64,
-                                      mkexpr(t1),
-                                      mkU64(0x00000001fffffffeULL)));
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
-                     break;
-                  }
-                  case 0x16: {  /* MULQ_S.W */
-                     DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t0, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            getIReg(rt), getIReg(rs)),
-                                      mkU8(0x1)));
-                     assign(t1, binop(Iop_CmpEQ32,
-                                      getIReg(rt), mkU32(0x80000000)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      getIReg(rs), mkU32(0x80000000)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              IRExpr_ITE(mkexpr(t2),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(mkexpr(t2),
-                                                       mkU32(0x7fffffff),
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t0))),
-                                            unop(Iop_64HIto32, mkexpr(t0))));
-                     break;
-                  }
-                  case 0x17: {  /* MULQ_RS.W */
-                     DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I1);
-
-                     assign(t0, binop(Iop_Add64,
-                                      binop(Iop_Shl64,
-                                            binop(Iop_MullS32,
-                                                  getIReg(rt),
-                                                  getIReg(rs)),
-                                            mkU8(0x1)),
-                                      mkU64(0x0000000080000000ULL)));
-                     assign(t1,
-                            binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
-                     assign(t2,
-                            binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              IRExpr_ITE(mkexpr(t2),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00200000)
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                            IRExpr_ITE(mkexpr(t2),
-                                                       mkU32(0x7fffffff),
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t0))),
-                                            unop(Iop_64HIto32, mkexpr(t0))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of ADDUH.QB/MUL.PH */
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add32x4,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
+
+               break;
             }
-            case 0x30: {  /* DPAQ.W.PH */
-               switch(sa) {
-                  case 0x0: {  /* DPA.W.PH */
-                     DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
 
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t1,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t2,
-                            binop(Iop_Add64,
-                                  getAcc(ac),
-                                  binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, mkexpr(t2));
-                     break;
-                  }
-                  case 0x1: {  /* DPS.W.PH */
-                     DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
+            case 0x03: { /* SRARI.D */
+               DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_SarN64x2,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN64x2,
+                            binop(Iop_ShlN64x2,
+                                  getWReg(ws),
+                                  mkU8(64 - m)),
+                            mkU8(63)));
 
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t1,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t2,
-                            binop(Iop_Sub64,
-                                  getAcc(ac),
-                                  binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, mkexpr(t2));
-                     break;
-                  }
-                  case 0x2: {  /* MULSA.W.PH */
-                     DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-
-                     assign(t4, getAcc(ac));
-                     assign(t0, binop(Iop_Mul32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32to16, getIReg(rs)))));
-                     assign(t1, binop(Iop_Mul32,
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      unop(Iop_16Sto32,
-                                           unop(Iop_32HIto16, getIReg(rs)))));
-                     assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
-                     putAcc(ac, binop(Iop_Add64,
-                                      mkexpr(t4),
-                                      unop(Iop_32Sto64, mkexpr(t2))));
-                     break;
-                  }
-                  case 0x3: {  /* DPAU.H.QBL */
-                     DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t1,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t2,
-                            unop(Iop_32Uto64,
-                                 binop(Iop_Add32,
-                                       mkexpr(t0),
-                                       mkexpr(t1))));
-                     assign(t3,
-                            binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
-                     putAcc(ac, mkexpr(t3));
-                     break;
-                  }
-                  case 0x4: {  /* DPAQ_S.W.PH */
-                     DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16, getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16, getIReg(rt)))
-                                           ),
-                                      mkU8(0x1)));
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t6),
-                                       IRExpr_ITE(mkexpr(t7),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t5)),
-                                       mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t9, binop(Iop_Add64,
-                                      binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
-                                      mkexpr(t0)));
-                     putAcc(ac, mkexpr(t9));
-                     break;
-                  }
-                  case 0x5: {  /* DPSQ_S.W.PH */
-                     DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5,
-                            binop(Iop_Shl64,
-                                  binop(Iop_MullS32,
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32to16, getIReg(rs))),
-                                        unop(Iop_16Sto32,
-                                             unop(Iop_32to16, getIReg(rt)))),
-                                  mkU8(0x1)));
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t6),
-                                       IRExpr_ITE(mkexpr(t7),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t5)),
-                                       mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t9,
-                            binop(Iop_Sub64,
-                                  mkexpr(t0),
-                                  binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
-                     putAcc(ac, mkexpr(t9));
-                     break;
-                  }
-                  case 0x6: {  /* MULSAQ_S.W.PH */
-                     DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I64);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-
-                     assign(t0, unop(Iop_16Sto32,
-                                     unop(Iop_32HIto16, getIReg(rs))));
-                     assign(t1, unop(Iop_16Sto32,
-                                     unop(Iop_32HIto16, getIReg(rt))));
-
-                     assign(t8, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 unop(Iop_16Uto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rs))),
-                                                 mkU32(0x8000))),
-                                    unop(Iop_1Sto32,
-                                         binop(Iop_CmpEQ32,
-                                               unop(Iop_16Uto32,
-                                                    unop(Iop_32HIto16,
-                                                         getIReg(rt))),
-                                               mkU32(0x8000)))));
-                     /* DSPControl_outflag:16+acc <- 1 */
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t8),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x00010000),
-                                                          mkU8(ac))),
-                                              getDSPControl()));
-
-                     /* tempB_31..0 */
-                     assign(t2,
-                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                             mkexpr(t8), mkU32(0x0)),
-                                       mkU32(0x7FFFFFFF),
-                                       binop(Iop_Shl32,
-                                             binop(Iop_Mul32,
-                                                   mkexpr(t0), mkexpr(t1)),
-                                             mkU8(1))));
-
-                     assign(t3, unop(Iop_16Sto32,
-                                     unop(Iop_32to16, getIReg(rs))));
-                     assign(t4, unop(Iop_16Sto32,
-                                     unop(Iop_32to16, getIReg(rt))));
-
-                     assign(t9, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 unop(Iop_16Uto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rs))),
-                                                 mkU32(0x8000))),
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 unop(Iop_16Uto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rt))),
-                                                 mkU32(0x8000)))));
-                     /* DSPControl_outflag:16+acc <- 1 */
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    mkexpr(t9),
-                                                    mkU32(0x0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x00010000),
-                                                          mkU8(ac))),
-                                              getDSPControl()));
-                     /* tempA_31..0 */
-                     assign(t5,
-                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                             mkexpr(t9),
-                                             mkU32(0x0)),
-                                       mkU32(0x7FFFFFFF),
-                                       binop(Iop_Shl32,
-                                             binop(Iop_Mul32,
-                                                   mkexpr(t3),
-                                                   mkexpr(t4)),
-                                             mkU8(1))));
-                     /* dotp_63..0 */
-                     assign(t6,
-                            binop(Iop_Sub64,
-                                  unop(Iop_32Sto64, mkexpr(t2)),
-                                  unop(Iop_32Sto64, mkexpr(t5))));
-                     /* tempC_63..0 */
-                     assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));
-
-                     putAcc(ac, mkexpr(t7));
-                     break;
-                  }
-                  case 0x7: {  /* DPAU.H.QBR */
-                     DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t1,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t2, unop(Iop_32Uto64,
-                                     binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
-                     assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
-                     putAcc(ac, mkexpr(t3));
-                     break;
-                  }
-                  case 0x8: {  /* DPAX.W.PH */
-                     DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t1,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t2,
-                            binop(Iop_Add64,
-                                  getAcc(ac),
-                                  binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, mkexpr(t2));
-                     break;
-                  }
-                  case 0x9: {  /* DPSX.W.PH */
-                     DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add64x2,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t1,
-                            unop(Iop_32Sto64,
-                                 binop(Iop_Mul32,
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32to16, getIReg(rs))),
-                                       unop(Iop_16Sto32,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t2,
-                            binop(Iop_Sub64,
-                                  getAcc(ac),
-                                  binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, mkexpr(t2));
-                     break;
-                  }
-                  case 0xB: {  /* DPSU.H.QBL */
-                     DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t1,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32HIto16, getIReg(rt))))));
-                     assign(t2,
-                            unop(Iop_32Uto64,
-                                 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
-                     assign(t3,
-                            binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
-                     putAcc(ac, mkexpr(t3));
-                     break;
-                  }
-                  case 0xC: {  /* DPAQ_SA.L.W */
-                     DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I64);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I1);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            getIReg(rs), getIReg(rt)),
-                                      mkU8(0x1)));
-
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      getIReg(rs),
-                                      mkU32(0x80000000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      getIReg(rt),
-                                      mkU32(0x80000000)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x7fffffffffffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5, binop(Iop_Add64,
-                                      unop(Iop_32Uto64,
-                                           unop(Iop_64to32, mkexpr(t0))),
-                                      unop(Iop_32Uto64,
-                                           unop(Iop_64to32, mkexpr(t4)))));
-                     assign(t6,
-                            binop(Iop_Add64,
-                                  binop(Iop_Add64,
-                                        unop(Iop_32Sto64,
-                                             unop(Iop_64HIto32, mkexpr(t0))),
-                                        unop(Iop_32Sto64,
-                                             unop(Iop_64HIto32, mkexpr(t4)))),
-                                  unop(Iop_32Uto64,
-                                       binop(Iop_And32,
-                                             unop(Iop_64HIto32, mkexpr(t5)),
-                                             mkU32(0x1)))));
-                     assign(t7, binop(Iop_32HLto64,
-                                      unop(Iop_64to32, mkexpr(t6)),
-                                      unop(Iop_64to32, mkexpr(t5))));
-                     assign(t8, binop(Iop_CmpEQ32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t6)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t6)),
-                                            mkU32(0x00000001))));
-                     assign(t9, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32,
-                                                 mkexpr(t6)),
-                                            mkU32(0x00000001)),
-                                      mkU32(0x1)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t8),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     putAcc(ac,
-                            IRExpr_ITE(mkexpr(t8),
-                                       mkexpr(t7),
-                                       IRExpr_ITE(mkexpr(t9),
-                                                  mkU64(0x8000000000000000ULL),
-                                                  mkU64(0x7fffffffffffffffULL)))
-                           );
-                     break;
-                  }
-                  case 0xD: {  /* DPSQ_SA.L.W */
-                     DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     t7 = newTemp(Ity_I64);
-                     t8 = newTemp(Ity_I1);
-                     t9 = newTemp(Ity_I1);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            getIReg(rs), getIReg(rt)),
-                                      mkU8(0x1)));
-
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      getIReg(rs),
-                                      mkU32(0x80000000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      getIReg(rt),
-                                      mkU32(0x80000000)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x7fffffffffffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5, binop(Iop_Sub64,
-                                      unop(Iop_32Uto64,
-                                           unop(Iop_64to32, mkexpr(t0))),
-                                      unop(Iop_32Uto64,
-                                           unop(Iop_64to32, mkexpr(t4)))));
-                     assign(t6, binop(Iop_Sub64,
-                                      binop(Iop_Add64,
-                                            unop(Iop_32Sto64,
-                                                 unop(Iop_64HIto32, mkexpr(t0))
-                                                ),
-                                            unop(Iop_32Sto64,
-                                                 unop(Iop_1Sto32,
-                                                      binop(Iop_CmpLT32U,
-                                                            unop(Iop_64to32,
-                                                                 mkexpr(t0)),
-                                                            unop(Iop_64to32,
-                                                                mkexpr(t4)))))),
-                                      unop(Iop_32Sto64,
-                                           unop(Iop_64HIto32, mkexpr(t4)))));
-                     assign(t7, binop(Iop_32HLto64,
-                                      unop(Iop_64to32, mkexpr(t6)),
-                                      unop(Iop_64to32, mkexpr(t5))));
-                     assign(t8, binop(Iop_CmpEQ32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t6)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t6)),
-                                            mkU32(0x00000001))));
-                     assign(t9, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t6)),
-                                            mkU32(0x00000001)),
-                                      mkU32(0x1)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t8),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     putAcc(ac,
-                            IRExpr_ITE(mkexpr(t8),
-                                       mkexpr(t7),
-                                       IRExpr_ITE(mkexpr(t9),
-                                                  mkU64(0x8000000000000000ULL),
-                                                  mkU64(0x7fffffffffffffffULL)))
-                           );
-                     break;
-                  }
-                  case 0xF: {  /* DPSU.H.QBR */
-                     DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-
-                     assign(t0,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16HIto8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t1,
-                            binop(Iop_Mul32,
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rs)))),
-                                  unop(Iop_8Uto32,
-                                       unop(Iop_16to8,
-                                            unop(Iop_32to16, getIReg(rt))))));
-                     assign(t2, unop(Iop_32Uto64,
-                                     binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
-                     assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
-                     putAcc(ac, mkexpr(t3));
+               break;
+            }
+         }
 
-                     break;
-                  }
-                  case 0x10: {  /* MAQ_SA.W.PHL */
-                     DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-                     assign(t1, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl register.
-                     */
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     /* Add intermediate product and value in the
-                        accumulator. */
-                     assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
-
-                     /* Compare bits 31 and 32 of the value in t5. */
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t5)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t5)),
-                                            mkU32(1))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     assign(t7,
-                            IRExpr_ITE(mkexpr(t6),
-                                       mkexpr(t5),
-                                       IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        binop(Iop_And32,
-                                                              unop(Iop_64HIto32,
-                                                                   mkexpr(t5)),
-                                                              mkU32(1)),
-                                                        mkU32(0x0)),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkU64(0xffffffff80000000ULL)))
-                           );
-                     putAcc(ac, mkexpr(t7));
-                     break;
-                  }
-                  case 0x12: {  /* MAQ_SA.W.PHR */
-                     DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-                     assign(t1, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl
-                        register. */
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-                     /* Add intermediate product and value in the
-                        accumulator. */
-                     assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
-
-                     /* Compare bits 31 and 32 of the value in t5. */
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32, mkexpr(t5)),
-                                                  mkU32(0x80000000)),
-                                            mkU8(31)),
-                                      binop(Iop_And32,
-                                            unop(Iop_64HIto32, mkexpr(t5)),
-                                            mkU32(1))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     assign(t7,
-                            IRExpr_ITE(mkexpr(t6),
-                                       mkexpr(t5),
-                                       IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                        binop(Iop_And32,
-                                                              unop(Iop_64HIto32,
-                                                                   mkexpr(t5)),
-                                                              mkU32(1)),
-                                                        mkU32(0x0)),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkU64(0xffffffff80000000ULL)))
-                           );
-                     putAcc(ac, mkexpr(t7));
-                     break;
-                  }
-                  case 0x14: {  /* MAQ_S.W.PHL */
-                     DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-
-                     assign(t5, getAcc(ac));
-
-                     assign(t0, unop(Iop_16Sto32,
-                                     unop(Iop_32HIto16, getIReg(rs))));
-                     assign(t1, unop(Iop_16Sto32,
-                                     unop(Iop_32HIto16, getIReg(rt))));
-
-                     assign(t2, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000))),
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t1),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000)))));
+         break;
+      }
 
-                     assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+      case 0x03: { /* SRLRI.df */
+         switch (df) {
+            case 0x00: { /* SRLRI.B */
+               DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_ShrN8x16,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN8x16,
+                            binop(Iop_ShlN8x16,
+                                  getWReg(ws),
+                                  mkU8(8 - m)),
+                            mkU8(7)));
 
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add8x16,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     assign(t4, unop(Iop_64to32,
-                                     binop(Iop_MullS32,
-                                           mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Add64,
-                                                 unop(Iop_32Sto64,
-                                                      binop(Iop_Shl32,
-                                                            mkexpr(t4),
-                                                            mkU8(0x1))),
-                                                 mkexpr(t5)),
-                                           binop(Iop_Add64,
-                                                 mkexpr(t5),
-                                                 unop(Iop_32Sto64,
-                                                      mkU32(0x7fffffff)))));
-                     break;
-                  }
-                  case 0x16: {  /* MAQ_S.W.PHR */
-                     DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-
-                     assign(t5, getAcc(ac));
-
-                     assign(t0, unop(Iop_16Sto32,
-                                     unop(Iop_32to16, getIReg(rs))));
-                     assign(t1, unop(Iop_16Sto32,
-                                     unop(Iop_32to16, getIReg(rt))));
-
-                     assign(t2, binop(Iop_And32,
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t0),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000))),
-                                      unop(Iop_1Sto32,
-                                           binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       mkexpr(t1),
-                                                       mkU32(0xffff)),
-                                                 mkU32(0x8000)))));
+               break;
+            }
 
-                     assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+            case 0x01: { /* SRLRI.H */
+               DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_ShrN16x8,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN16x8,
+                            binop(Iop_ShlN16x8,
+                                  getWReg(ws),
+                                  mkU8(16 - m)),
+                            mkU8(15)));
 
-                     putDSPControl(IRExpr_ITE(mkexpr(t3),
-                                              getDSPControl(),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add16x8,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     assign(t4, unop(Iop_64to32,
-                                     binop(Iop_MullS32,
-                                           mkexpr(t0), mkexpr(t1))));
-                     putAcc(ac, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_Add64,
-                                                 unop(Iop_32Sto64,
-                                                      binop(Iop_Shl32,
-                                                            mkexpr(t4),
-                                                            mkU8(0x1))),
-                                                 mkexpr(t5)),
-                                           binop(Iop_Add64,
-                                                 mkexpr(t5),
-                                                 unop(Iop_32Sto64,
-                                                      mkU32(0x7fffffff)))));
-                     break;
-                  }
-                  case 0x18: {  /* DPAQX_S.W.PH */
-                     DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                  mkU32(0x1),
-                                                                  mkU8(ac+16))),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t6),
-                                       IRExpr_ITE(mkexpr(t7),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t5)),
-                                       mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t9, binop(Iop_Add64,
-                                      binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
-                                      mkexpr(t0)));
-                     putAcc(ac, mkexpr(t9));
-                     break;
-                  }
-                  case 0x19: {  /* DPSQX_S.W.PH */
-                     DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t5, binop(Iop_Shl64,
-                                      binop(Iop_MullS32,
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32to16,
-                                                      getIReg(rs))),
-                                            unop(Iop_16Sto32,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                      mkU8(0x1)));
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t6),
-                                       IRExpr_ITE(mkexpr(t7),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t5)),
-                                       mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     assign(t9, binop(Iop_Sub64,
-                                     mkexpr(t0),
-                                     binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
-                     putAcc(ac, mkexpr(t9));
-                     break;
-                  }
-                  case 0x1A: {  /* DPAQX_SA.W.PH */
-                     DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     /* Calculate the first cross dot product and saturate if
-                        needed. */
-                     assign(t1, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl
-                        register. */
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t2)),
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t3))),
-                                                 mkU32(0)),
-                                           mkU64(0x000000007fffffffULL),
-                                           mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t2)),
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t3))),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16))),
-                                              getDSPControl()));
-                     /* Calculate second cross dot product and saturate if
-                        needed. */
-                     assign(t5, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl
-                        register. */
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t6)),
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t7))),
-                                                 mkU32(0)),
-                                           mkU64(0x000000007fffffffULL),
-                                           mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t6)),
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t7))),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16))),
-                                              getDSPControl()));
-                     /* Subtract intermediate products from value in the
-                        accumulator. */
-                     assign(t9,
-                            binop(Iop_Add64,
-                                  mkexpr(t0),
-                                  binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
-
-                     putAcc(ac,
-                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                             binop(Iop_And32,
-                                                   unop(Iop_64HIto32,
-                                                        mkexpr(t9)),
-                                                   mkU32(0x80000000)),
-                                             mkU32(0x0)),
-                                       IRExpr_ITE(binop(Iop_CmpNE32,
-                                                        unop(Iop_64HIto32,
-                                                             binop(Iop_Shl64,
-                                                                   mkexpr(t9),
-                                                                   mkU8(1))),
-                                                        mkU32(0x0)),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t9)),
-                                       IRExpr_ITE(binop(Iop_CmpNE32,
-                                                        unop(Iop_64HIto32,
-                                                             binop(Iop_Shl64,
-                                                                   mkexpr(t9),
-                                                                   mkU8(1))),
-                                                        mkU32(0xffffffff)),
-                                                  mkU64(0xffffffff80000000ULL),
-                                                  mkexpr(t9))));
-                     assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  unop(Iop_64to32,
-                                                       mkexpr(t9)),
-                                                  unop(Iop_64to32,
-                                                       getAcc(ac))),
-                                           getDSPControl(),
-                                           binop(Iop_Or32,
-                                                 getDSPControl(),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkU8(ac+16)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t9)),
-                                                    unop(Iop_64HIto32,
-                                                         getAcc(ac))),
-                                              mkexpr(t10),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     break;
-                  }
-                  case 0x1B: {  /* DPSQX_SA.W.PH */
-                     DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
-                     vassert(!mode64);
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I1);
-                     t7 = newTemp(Ity_I1);
-                     t8 = newTemp(Ity_I64);
-                     t9 = newTemp(Ity_I64);
-                     t10 = newTemp(Ity_I32);
-
-                     assign(t0, getAcc(ac));
-                     /* Calculate the first cross dot product and saturate if
-                        needed. */
-                     assign(t1, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl
-                        register. */
-                     assign(t2, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t3, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t2)),
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t3))),
-                                                 mkU32(0)),
-                                           mkU64(0x000000007fffffffULL),
-                                           mkexpr(t1)));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t2)),
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t3))),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16))),
-                                              getDSPControl()));
-                     /* Calculate second cross dot product and saturate if
-                        needed. */
-                     assign(t5, unop(Iop_32Sto64,
-                                     binop(Iop_Shl32,
-                                           binop(Iop_Mul32,
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32to16,
-                                                           getIReg(rs))),
-                                                 unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           getIReg(rt)))),
-                                           mkU8(0x1))));
-
-                     /* If both input arguments are equal 0x8000, saturate
-                        intermediate product and write to DSPControl
-                        register. */
-                     assign(t6, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32to16, getIReg(rs))),
-                                      mkU32(0x00008000)));
-                     assign(t7, binop(Iop_CmpEQ32,
-                                      unop(Iop_16Uto32,
-                                           unop(Iop_32HIto16, getIReg(rt))),
-                                      mkU32(0x00008000)));
-
-                     assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t6)),
-                                                       unop(Iop_1Sto32,
-                                                            mkexpr(t7))),
-                                                 mkU32(0)),
-                                           mkU64(0x000000007fffffffULL),
-                                           mkexpr(t5)));
-
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t6)),
-                                                          unop(Iop_1Sto32,
-                                                               mkexpr(t7))),
-                                                    mkU32(0)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16))),
-                                              getDSPControl()));
-                     /* Subtract intermediate products from value in the
-                        accumulator. */
-                     assign(t9,
-                            binop(Iop_Sub64,
-                                  mkexpr(t0),
-                                  binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
-
-                     putAcc(ac,
-                            IRExpr_ITE(binop(Iop_CmpEQ32,
-                                             binop(Iop_And32,
-                                                   unop(Iop_64HIto32,
-                                                        mkexpr(t9)),
-                                                   mkU32(0x80000000)),
-                                             mkU32(0x0)),
-                                       IRExpr_ITE(binop(Iop_CmpNE32,
-                                                        unop(Iop_64HIto32,
-                                                             binop(Iop_Shl64,
-                                                                   mkexpr(t9),
-                                                                   mkU8(1))),
-                                                        mkU32(0x0)),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t9)),
-                                       IRExpr_ITE(binop(Iop_CmpNE32,
-                                                        unop(Iop_64HIto32,
-                                                             binop(Iop_Shl64,
-                                                                   mkexpr(t9),
-                                                                   mkU8(1))),
-                                                        mkU32(0xffffffff)),
-                                                  mkU64(0xffffffff80000000ULL),
-                                                  mkexpr(t9))));
-                     assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  unop(Iop_64to32,
-                                                       mkexpr(t9)),
-                                                  unop(Iop_64to32,
-                                                       getAcc(ac))),
-                                           getDSPControl(),
-                                           binop(Iop_Or32,
-                                                 getDSPControl(),
-                                                 binop(Iop_Shl32,
-                                                       mkU32(0x1),
-                                                       mkU8(ac+16)))));
-                     putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t9)),
-                                                    unop(Iop_64HIto32,
-                                                         getAcc(ac))),
-                                              mkexpr(t10),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    binop(Iop_Shl32,
-                                                          mkU32(0x1),
-                                                          mkU8(ac+16)))));
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of DPAQ.W.PH */
+               break;
             }
-            case 0x31: {  /* APPEND */
-               switch(sa) {
-                  case 0x0: {  /* APPEND */
-                     DIP("append r%u, r%u, %u", rt, rs, rd);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
 
-                     assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));
+            case 0x02: { /* SRLRI.W */
+               DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_ShrN32x4,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN32x4,
+                            binop(Iop_ShlN32x4,
+                                  getWReg(ws),
+                                  mkU8(32 - m)),
+                            mkU8(31)));
+
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add32x4,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                     if (31 == rd) {
-                        putIReg(rt, binop(Iop_Or32,
-                                          mkexpr(t1),
-                                          binop(Iop_And32,
-                                                getIReg(rs),
-                                                mkU32(0x7fffffff))));
-                     } else if (1 == rd) {
-                        putIReg(rt,
-                                binop(Iop_Or32,
-                                      mkexpr(t1),
-                                      binop(Iop_And32,
-                                            getIReg(rs), mkU32(0x1))));
-                     } else {
-                        assign(t2,
-                               unop(Iop_Not32,
-                                    binop(Iop_Shl32,
-                                          mkU32(0xffffffff), mkU8(rd))));
+               break;
+            }
 
-                        putIReg(rt, binop(Iop_Or32,
-                                          mkexpr(t1),
-                                          binop(Iop_And32,
-                                                getIReg(rs), mkexpr(t2))));
-                     }
-                     break;
-                  }
-                  case 0x1: {  /* PREPEND */
-                     DIP("prepend r%u, r%u, %u", rt, rs, rd);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-
-                     if (0 != rd) {
-                        assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));
-
-                        if (31 == rd) {
-                           putIReg(rt, binop(Iop_Or32,
-                                             mkexpr(t1),
-                                             binop(Iop_Shl32,
-                                                   binop(Iop_And32,
-                                                         getIReg(rs),
-                                                         mkU32(0x7fffffff)),
-                                                   mkU8(1))));
-                        } else if (1 == rd) {
-                           putIReg(rt, binop(Iop_Or32,
-                                             mkexpr(t1),
-                                             binop(Iop_Shl32,
-                                                   binop(Iop_And32,
-                                                         getIReg(rs),
-                                                         mkU32(0x1)),
-                                                   mkU8(31))));
-                        } else {
-                           assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));
+            case 0x03: { /* SRLRI.D */
+               DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_ShrN64x2,
+                            getWReg(ws),
+                            mkU8(m)));
+               assign(t2,
+                      binop(Iop_ShrN64x2,
+                            binop(Iop_ShlN64x2,
+                                  getWReg(ws),
+                                  mkU8(64 - m)),
+                            mkU8(63)));
 
-                           assign(t3, unop(Iop_Not32,
-                                           binop(Iop_Shl32,
-                                                 mkU32(0xffffffff),
-                                                 unop(Iop_32to8, mkexpr(t2)))));
+               if (m)
+                  putWReg(wd,
+                          binop(Iop_Add64x2,
+                                mkexpr(t1), mkexpr(t2)));
+               else putWReg(wd, mkexpr(t1));
 
-                           putIReg(rt, binop(Iop_Or32,
-                                             mkexpr(t1),
-                                             binop(Iop_Shl32,
-                                                   binop(Iop_And32,
-                                                         getIReg(rs),
-                                                         mkexpr(t3)),
-                                                   mkU8(32-rd))));
-                        }
-                     }
-                     break;
-                  }
-                  case 0x10: {  /* BALIGN */
-                     DIP("balign r%u, r%u, %u", rt, rs, rd);
-                     vassert(!mode64);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-
-                     if ((2 != rd) && (0 != rd)) {
-                        assign(t1, binop(Iop_Shl32,
-                                         binop(Iop_And32,
-                                               mkU32(rd), mkU32(0x3)),
-                                         mkU8(0x3)));
-                        assign(t2, binop(Iop_Shl32,
-                                         getIReg(rt),
-                                         unop(Iop_32to8, mkexpr(t1))));
-                        assign(t3, binop(Iop_Shr32,
-                                         getIReg(rs),
-                                         unop(Iop_32to8,
-                                              binop(Iop_Shl32,
-                                                    binop(Iop_Sub32,
-                                                          mkU32(0x4),
-                                                          binop(Iop_And32,
-                                                                mkU32(rd),
-                                                                mkU32(0x3))),
-                                                    mkU8(0x3)))));
-                        putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
-                     }
-                     break;
-                  }
-                  default:
-                     return -1;
-               }
-               break;  /* end of APPEND */
+               break;
             }
-            default:
-               return -1;
          }
+
          break;
       }
+
       default:
-            return -1;
+         return -1;
    }
+
    return 0;
 }
 
-static Int msa_I8_logical(UInt cins, UChar wd, UChar ws) {
-   IRTemp t1, t2;
+static Int msa_3R_0D(UInt cins, UChar wd, UChar ws)   /* 3R (0x0D) */
+{
+   IRTemp t1, t2, t3;
    UShort operation;
-   UChar i8;
+   UChar df, wt;
+
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
-   operation = (cins >> 24) & 3;
-   i8 = (cins & 0x00FF0000) >> 16;
    switch (operation) {
-      case 0x00: {  /* ANDI.B */
-            DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t1, getWReg(ws));
-            assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
-            break;
+      case 0x00: { /* SLL.df */
+         switch (df) {
+            case 0x00: { /* SLL.B */
+               DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x01: { /* SLL.H */
+               DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* SLL.W */
+               DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* SLL.D */
+               DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x01: { /* ORI.B */
-            DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t1, getWReg(ws));
-            assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            break;
+         break;
+      }
+
+      case 0x01: { /* SRA.df */
+         switch (df) {
+            case 0x00: { /* SRA.B */
+               DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x01: { /* SRA.H */
+               DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* SRA.W */
+               DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* SRA.D */
+               DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x02: { /* NORI.B */
-            DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t1, getWReg(ws));
-            assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
-                                                mkexpr(t1), mkexpr(t2))));
-            break;
+         break;
+      }
+
+      case 0x02: { /* SRL.df */
+         switch (df) {
+            case 0x00: { /* SRL.B */
+               DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x01: { /* SRL.H */
+               DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* SRL.W */
+               DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* SRL.D */
+               DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x03: {  /* XORI.B */
-            DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t1, getWReg(ws));
-            assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
-            break;
+         break;
+      }
+
+      case 0x03: { /* BCLR.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
+
+         switch (df) {
+            case 0x00: { /* BCLR.B */
+               DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2, binop(Iop_Shl8x16,
+                                binop(Iop_64HLtoV128,
+                                      mkU64(tmp), mkU64(tmp)),
+                                getWReg(wt)));
+               break;
+            }
+
+            case 0x01: { /* BCLR.H */
+               DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2,
+                      binop(Iop_Shl16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x02: { /* BCLR.W */
+               DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 32);
+               assign(t2,
+                      binop(Iop_Shl32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x03: { /* BCLR.D */
+               DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
+               assign(t2,
+                      binop(Iop_Shl64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
          }
 
-      default:
-         return -1;
-   }
+         assign(t3,
+                binop(Iop_AndV128,
+                      mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-   return 0;
-}
+      case 0x04: { /* BSET.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
 
-static Int msa_I8_branch(UInt cins, UChar wd, UChar ws) {
-   IRTemp t1, t2, t3, t4;
-   UShort operation;
-   UChar i8;
+         switch (df) {
+            case 0x00: { /* BSET.B */
+               DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2,
+                      binop(Iop_Shl8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
 
-   operation = (cins >> 24) & 3;
-   i8 = (cins & 0x00FF0000) >> 16;
-   switch (operation) {
-      case 0x00: { /* BMNZI.B */
-            DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            t4 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
-            assign(t2, binop(Iop_AndV128, getWReg(wd),
-                                          unop(Iop_NotV128, mkexpr(t4))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
+            case 0x01: { /* BSET.H */
+               DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2,
+                      binop(Iop_Shl16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x02: { /* BSET.W */
+               DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 32);
+               assign(t2,
+                      binop(Iop_Shl32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x03: { /* BSET.D */
+               DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
+               assign(t2,
+                      binop(Iop_Shl64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
          }
 
-      case 0x01: { /* BMZI.B */
-            DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            t4 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
-            assign(t2, binop(Iop_AndV128, getWReg(ws),
-                             unop(Iop_NotV128, mkexpr(t4))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
+
+      case 0x05: { /* BNEG.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         ULong tmp = 1;
+         assign(t1, getWReg(ws));
+
+         switch (df) {
+            case 0x00: { /* BNEG.B */
+               DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+                      (tmp << 32) | (tmp << 24) | (tmp << 16) |
+                      (tmp << 8);
+               assign(t2,
+                      binop(Iop_Shl8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x01: { /* BNEG.H */
+               DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+               assign(t2,
+                      binop(Iop_Shl16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x02: { /* BNEG.W */
+               DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
+               tmp |= (tmp << 32);
+               assign(t2,
+                      binop(Iop_Shl32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
+
+            case 0x03: { /* BNEG.D */
+               DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
+               assign(t2,
+                      binop(Iop_Shl64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               break;
+            }
          }
 
-      case 0x02: { /* BSELI.B */
-            DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            t4 = newTemp(Ity_V128);
-            ULong tmp = i8;
-            tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                   (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                   (tmp << 8);
-            assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
-            assign(t2, binop(Iop_AndV128, getWReg(ws),
-                             unop(Iop_NotV128, getWReg(wd))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
+         assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
+
+      case 0x06: { /* BINSL.df */
+         switch (df) {
+            case 0x00: { /* BINSL.B */
+               DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8080808080808080ULL;
+               assign(t1,
+                      binop(Iop_Sar8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
+
+            case 0x01: { /* BINSL.H */
+               DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000800080008000ULL;
+               assign(t1,
+                      binop(Iop_Sar16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
+
+            case 0x02: { /* BINSL.W */
+               DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000000080000000ULL;
+               assign(t1,
+                      binop(Iop_Sar32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
+
+            case 0x03: { /* BINSL.D */
+               DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0x8000000000000000ULL;
+               assign(t1,
+                      binop(Iop_Sar64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(wd)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(ws)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
+
+      case 0x07: { /* BINSR.df */
+         switch (df) {
+            case 0x00: { /* BINSR.B */
+               DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
+               assign(t1,
+                      binop(Iop_Shl8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-   return 0;
-}
+            case 0x01: { /* BINSR.H */
+               DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
+               assign(t1,
+                      binop(Iop_Shl16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-static Int msa_I8_shift(UInt cins, UChar wd, UChar ws) {
-   IRTemp t1, t2;
-   UShort operation;
-   UChar i8;
+            case 0x02: { /* BINSR.W */
+               DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
+               assign(t1,
+                      binop(Iop_Shl32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-   operation = (cins >> 24) & 3;
-   i8 = (cins & 0x00FF0000) >> 16;
-   switch (operation) {
-      case 0x00: { /* SHF.B */
-            DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(wd));
-            assign(t2, getWReg(ws));
-            Int i;
-            IRTemp tmp[16];
-
-            for (i = 0; i < 16; i++) {
-               tmp[i] = newTemp(Ity_I8);
-               assign(tmp[i],
-                      binop(Iop_GetElem8x16, mkexpr(t2),
-                            mkU8(i - (i % 4) +
-                                 ((i8 >> (i % 4) * 2) & 0x03))));
-            }
-
-            putWReg(wd, binop(Iop_64HLtoV128,
-                              binop(Iop_32HLto64,
-                                    binop(Iop_16HLto32,
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[15]),
-                                                mkexpr(tmp[14])),
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[13]),
-                                                mkexpr(tmp[12]))),
-                                    binop(Iop_16HLto32,
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[11]),
-                                                mkexpr(tmp[10])),
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[9]),
-                                                mkexpr(tmp[8])))),
-                              binop(Iop_32HLto64,
-                                    binop(Iop_16HLto32,
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[7]),
-                                                mkexpr(tmp[6])),
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[5]),
-                                                mkexpr(tmp[4]))),
-                                    binop(Iop_16HLto32,
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[3]),
-                                                mkexpr(tmp[2])),
-                                          binop(Iop_8HLto16,
-                                                mkexpr(tmp[1]),
-                                                mkexpr(tmp[0]))))));
-            break;
-         }
+            case 0x03: { /* BINSR.D */
+               DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               ULong tmp = -2;
+               assign(t1,
+                      binop(Iop_Shl64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(tmp), mkU64(tmp)),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128, mkexpr(t1)),
+                            getWReg(ws)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            mkexpr(t1), getWReg(wd)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-      case 0x01: { /* SHF.H */
-            DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(wd));
-            assign(t2, getWReg(ws));
-            Int i;
-            IRTemp tmp[8];
-
-            for (i = 0; i < 8; i++) {
-               tmp[i] = newTemp(Ity_I16);
-               assign(tmp[i],
-                      binop(Iop_GetElem16x8, mkexpr(t2),
-                            mkU8(i - (i % 4) +
-                                 ((i8 >> (i % 4) * 2) & 0x03))));
-            }
-
-            putWReg(wd, binop(Iop_64HLtoV128,
-                              binop(Iop_32HLto64,
-                                    binop(Iop_16HLto32,
-                                          mkexpr(tmp[7]), mkexpr(tmp[6])),
-                                    binop(Iop_16HLto32,
-                                          mkexpr(tmp[5]), mkexpr(tmp[4]))),
-                              binop(Iop_32HLto64,
-                                    binop(Iop_16HLto32,
-                                          mkexpr(tmp[3]), mkexpr(tmp[2])),
-                                    binop(Iop_16HLto32,
-                                          mkexpr(tmp[1]), mkexpr(tmp[0])))));
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* SHF.W */
-            DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(wd));
-            assign(t2, getWReg(ws));
-            Int i;
-            IRTemp tmp[4];
-
-            for (i = 0; i < 4; i++) {
-               tmp[i] = newTemp(Ity_I32);
-               assign(tmp[i],
-                      binop(Iop_GetElem32x4, mkexpr(t2),
-                            mkU8(i - (i % 4) +
-                                 ((i8 >> (i % 4) * 2) & 0x03))));
-            }
-
-            putWReg(wd, binop(Iop_64HLtoV128,
-                              binop(Iop_32HLto64,
-                                    mkexpr(tmp[3]), mkexpr(tmp[2])),
-                              binop(Iop_32HLto64,
-                                    mkexpr(tmp[1]), mkexpr(tmp[0]))));
-            break;
-         }
+         break;
+      }
 
       default:
          return -1;
@@ -12920,8 +6115,9 @@ static Int msa_I8_shift(UInt cins, UChar wd, UChar ws) {
    return 0;
 }
 
-static Int msa_I5_06(UInt cins, UChar wd, UChar ws) { /* I5 (0x06) */
-   IRTemp t1, t2, t3;
+static Int msa_3R_0E(UInt cins, UChar wd, UChar ws)   /* 3R (0x0E) */
+{
+   IRTemp t1, t2, t3, t4;
    UShort operation;
    UChar df, wt;
 
@@ -12930,809 +6126,878 @@ static Int msa_I5_06(UInt cins, UChar wd, UChar ws) { /* I5 (0x06) */
    wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* ADDVI */
-            ULong tmp = wt;
+      case 0x00: { /* ADDV.df */
+         switch (df) {
+            case 0x00: { /* ADDV.B */
+               DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-            switch (df) {
-               case 0x00: { /* ADDVI.B */
-                     DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* ADDV.H */
+               DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* ADDVI.H */
-                     DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* ADDV.W */
+               DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* ADDVI.W */
-                     DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* ADDV.D */
+               DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* ADDVI.D */
-                     DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x01: { /* SUBV.df */
+         switch (df) {
+            case 0x00: { /* SUBV.B */
+               DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            case 0x01: { /* SUBV.H */
+               DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* SUBV.W */
+               DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* SUBV.D */
+               DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x01: { /* SUBVI */
-            ULong tmp = wt;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* SUBVI.B */
-                     DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x02: { /* MAX_S.df */
+         switch (df) {
+            case 0x00: { /* MAX_S.B */
+               DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* SUBVI.H */
-                     DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MAX_S.H */
+               DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* SUBVI.W */
-                     DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MAX_S.W */
+               DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* SUBVI.D */
-                     DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* MAX_S.D */
+               DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* MAXI_S */
-            ULong tmp = wt;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MAXI_S.B */
-                     DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     char stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UChar)stemp;
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2,binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x03: { /* MAX_U.df */
+         switch (df) {
+            case 0x00: { /* MAX_U.B */
+               DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* MAXI_S.H */
-                     DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     short stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UShort)stemp;
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MAX_U.H */
+               DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* MAXI_S.W */
-                     DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     int stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UInt)stemp;
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MAX_U.W */
+               DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* MAXI_S.D */
-                     DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     Long stemp = ((Long)tmp << 59) >> 59;
-                     tmp = stemp;
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* MAX_U.D */
+               DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* MAXI_U */
-            ULong tmp = wt;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MAXI_U.B */
-                     DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x04: { /* MIN_S.df */
+         switch (df) {
+            case 0x00: { /* MIN_S.B */
+               DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* MAXI_U.H */
-                     DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MIN_S.H */
+               DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* MAXI_U.W */
-                     DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MIN_S.W */
+               DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* MAXI_U.D */
-                     DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* MIN_S.D */
+               DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x05: { /* MIN_U.df */
+         switch (df) {
+            case 0x00: { /* MIN_U.B */
+               DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x01: { /* MIN_U.H */
+               DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x02: { /* MIN_U.W */
+               DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* MIN_U.D */
+               DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x04: { /* MINI_S */
-            ULong tmp = wt;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MINI_S.B */
-                     DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     char stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UChar)stemp;
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x06: { /* MAX_A.df */
+         switch (df) {
+            case 0x00: { /* MAX_A.B */
+               DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+               assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+               assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(ws)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(wt))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* MINI_S.H */
-                     DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     short stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UShort)stemp;
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MAX_A.H */
+               DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+               assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+               assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(ws)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(wt))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* MINI_S.W */
-                     DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     int stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UInt)stemp;
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MAX_A.W */
+               DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+               assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+               assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(ws)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(wt))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* MINI_S.D */
-                     DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     Long stemp = ((Long)tmp << 59) >> 59;
-                     tmp = stemp;
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* MAX_A.D */
+               DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+               assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+               assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(ws)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(wt))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* MINI_U */
-            ULong tmp = wt;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MINI_U.B */
-                     DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x07: { /* MIN_A.df */
+         switch (df) {
+            case 0x00: { /* MIN_A.B */
+               DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+               assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+               assign(t4, binop(Iop_OrV128,
+                                binop(Iop_CmpGT8Ux16,
+                                      mkexpr(t1), mkexpr(t2)),
+                                binop(Iop_CmpEQ8x16,
+                                      mkexpr(t1), mkexpr(t2))));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(wt)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(ws))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* MINI_U.H */
-                     DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MIN_A.H */
+               DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+               assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+               assign(t4, binop(Iop_OrV128,
+                                binop(Iop_CmpGT16Ux8,
+                                      mkexpr(t1), mkexpr(t2)),
+                                binop(Iop_CmpEQ16x8,
+                                      mkexpr(t1), mkexpr(t2))));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(wt)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(ws))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* MINI_U.W */
-                     DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MIN_A.W */
+               DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+               assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+               assign(t4, binop(Iop_OrV128,
+                                binop(Iop_CmpGT32Ux4,
+                                      mkexpr(t1), mkexpr(t2)),
+                                binop(Iop_CmpEQ32x4,
+                                      mkexpr(t1), mkexpr(t2))));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(wt)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(ws))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* MINI_U.D */
-                     DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* MIN_A.D */
+               DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+               assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+               assign(t4, binop(Iop_OrV128,
+                                binop(Iop_CmpGT64Ux2,
+                                      mkexpr(t1), mkexpr(t2)),
+                                binop(Iop_CmpEQ64x2,
+                                      mkexpr(t1), mkexpr(t2))));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_AndV128,
+                                      mkexpr(t4),
+                                      getWReg(wt)),
+                                binop(Iop_AndV128,
+                                      unop(Iop_NotV128, mkexpr(t4)),
+                                      getWReg(ws))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      default: {
-            return -1;
-         }
+         break;
+      }
+
+      default:
+         return -1;
    }
 
    return 0;
 }
 
-static Int msa_I5_07(UInt cins, UChar wd, UChar ws) { /* I5 (0x07) / I10 */
+static Int msa_3R_0F(UInt cins, UChar wd, UChar ws)   /* 3R (0x0F) */
+{
    IRTemp t1, t2, t3;
    UShort operation;
-   UChar df, i5;
+   UChar df, wt;
 
    operation = (cins & 0x03800000) >> 23;
    df = (cins & 0x00600000) >> 21;
-   i5 = (cins & 0x001F0000) >> 16;
+   wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: {
-            ULong tmp = i5;
-
-            switch (df) {
-               case 0x00: { /* CEQI.B */
-                     DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     char stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UChar)stemp;
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* CEQI.H */
-                     DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     short stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UShort)stemp;
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x02: { /* CEQI.W */
-                     DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     int stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UInt)stemp;
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x03: { /* CEQI.D */
-                     DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     Long stemp = ((Long)tmp << 59) >> 59;
-                     tmp = stemp;
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x00: { /* CEQ.df */
+         switch (df) {
+            case 0x00: { /* CEQ.B */
+               DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
-         }
-
-      case 0x02: { /* CLTI_S.df */
-            ULong tmp = i5;
-
-            switch (df) {
-               case 0x00: { /* CLTI_S.B */
-                     DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     char stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UChar)stemp;
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* CLTI_S.H */
-                     DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     short stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UShort)stemp;
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x02: { /* CLTI_S.W */
-                     DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     int stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UInt)stemp;
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* CEQ.H */
+               DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* CLTI_S.D */
-                     DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     Long stemp = ((Long)tmp << 59) >> 59;
-                     tmp = stemp;
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* CEQ.W */
+               DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* CEQ.D */
+               DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* CLTI_U.df */
-            ULong tmp = i5;
-
-            switch (df) {
-               case 0x00: { /* CLTI_U.B */
-                     DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* CLTI_U.H */
-                     DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x02: { /* CLT_S.df */
+         switch (df) {
+            case 0x00: { /* CLT_S.B */
+               DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* CLTI_U.W */
-                     DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* CLT_S.H */
+               DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* CLTI_U.D */
-                     DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* CLT_S.W */
+               DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
-         }
+            case 0x03: { /* CLT_S.D */
+               DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-      case 0x04: { /* CLEI_S.df */
-            ULong tmp = i5;
+            default:
+               return -1;
+         }
 
-            switch (df) {
-               case 0x00: { /* CLEI_S.B */
-                     DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     char stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UChar)stemp;
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
-                                                      mkexpr(t2), mkexpr(t1)),
-                                                  binop(Iop_CmpEQ8x16,
-                                                      mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* CLEI_S.H */
-                     DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     short stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UShort)stemp;
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
-                                                      mkexpr(t2), mkexpr(t1)),
-                                                  binop(Iop_CmpEQ16x8,
-                                                      mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x03: { /* CLT_U.df */
+         switch (df) {
+            case 0x00: { /* CLT_U.B */
+               DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* CLEI_S.W */
-                     DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     int stemp = ((int)tmp << 27) >> 27;
-                     tmp = (UInt)stemp;
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT32Sx4,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ32x4,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* CLT_U.H */
+               DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* CLEI_S.D */
-                     DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     Long stemp = ((Long)tmp << 59) >> 59;
-                     tmp = stemp;
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT64Sx2,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ64x2,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* CLT_U.W */
+               DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* CLT_U.D */
+               DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* CLEI_U.df */
-            ULong tmp = i5;
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* CLEI_U.B */
-                     DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT8Ux16,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ8x16,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x04: { /* CLE_S.df */
+         switch (df) {
+            case 0x00: { /* CLE_S.B */
+               DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT8Sx16,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ8x16,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* CLEI_U.H */
-                     DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT16Ux8,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ16x8,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* CLE_S.H */
+               DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT16Sx8,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ16x8,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* CLEI_U.W */
-                     DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     tmp |= (tmp << 32);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT32Ux4,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ32x4,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* CLE_S.W */
+               DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT32Sx4,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ32x4,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* CLEI_U.D */
-                     DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT64Ux2,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ64x2,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* CLE_S.D */
+               DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT64Sx2,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ64x2,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x06: { /* LDI.df */
-            ULong tmp;
-            UShort s10;
-            s10 = (cins & 0x001FF800) >> 11;
-            switch (df) {
-               case 0x00: /* LDI.B */
-                  DIP("LDI.B w%d, %d", wd, s10);
-                  tmp = s10 & 0xFFl;
-                  tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
-                        | (tmp << 32) | (tmp << 40) | (tmp << 48) |
-                        (tmp << 56);
-                  break;
+         break;
+      }
 
-               case 0x01: /* LDI.H */
-                  DIP("LDI.H w%d, %d", wd, s10);
-                  tmp = extend_s_10to16(s10);
-                  tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
-                  break;
+      case 0x05: { /* CLE_U.df */
+         switch (df) {
+            case 0x00: { /* CLE_U.B */
+               DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT8Ux16,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ8x16,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: /* LDI.W */
-                  DIP("LDI.W w%d, %d", wd, s10);
-                  tmp = extend_s_10to32(s10);
-                  tmp = tmp | (tmp << 32);
-                  break;
+            case 0x01: { /* CLE_U.H */
+               DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT16Ux8,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ16x8,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: /* LDI.D */
-                  DIP("LDI.D w%d, %d", wd, s10);
-                  tmp = extend_s_10to64(s10);
-                  break;
+            case 0x02: { /* CLE_U.W */
+               DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT32Ux4,
+                                      mkexpr(t2), mkexpr(t1)),
+                                binop(Iop_CmpEQ32x4,
+                                      mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* CLE_U.D */
+               DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpGT64Ux2,
+                                  mkexpr(t2), mkexpr(t1)),
+                            binop(Iop_CmpEQ64x2,
+                                  mkexpr(t1), mkexpr(t2))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -13740,472 +7005,707 @@ static Int msa_I5_07(UInt cins, UChar wd, UChar ws) { /* I5 (0x07) / I10 */
    return 0;
 }
 
-static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) { /* BIT (0x09) */
-   IRTemp t1, t2, t3;
+static Int msa_3R_10(UInt cins, UChar wd, UChar ws)   /* 3R (0x10) */
+{
+   IRTemp t1, t2, t3, t4;
    UShort operation;
-   UChar df, m;
+   UChar df, wt;
 
    operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x007F0000) >> 16;
-
-   if ((df & 0x70) == 0x70) {        // 111mmmm; b
-      m = df & 0x07;
-      df = 0;
-   } else if ((df & 0x60) == 0x60) { // 110mmmm; h
-      m = df & 0x0F;
-      df = 1;
-   } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
-      m = df & 0x1F;
-      df = 2;
-   } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
-      m = df & 0x3F;
-      df = 3;
-   }
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* SLLI.df */
-            switch (df) {
-               case 0x00: { /* SLLI.B */
-                     DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+      case 0x00: { /* ADD_A.df */
+         switch (df) {
+            case 0x00: { /* ADD_A.B */
+               DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+               assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+               assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* SLLI.H */
-                     DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* ADD_A.H */
+               DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+               assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+               assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* SLLI.W */
-                     DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* ADD_A.W */
+               DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+               assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+               assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* SLLI.D */
-                     DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x03: { /* ADD_A.D */
+               DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+               assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+               assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x01: { /* SRAI.df */
-            switch (df) {
-               case 0x00: { /* SRAI.B */
-                     DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* SRAI.H */
-                     DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+      case 0x01: { /* ADDS_A.df */
+         switch (df) {
+            case 0x00: { /* ADDS_A.B */
+               DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+               assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+               assign(t3, binop(Iop_SarN8x16,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                mkU8(7)));
+               assign(t4, binop(Iop_SarN8x16,
+                                binop(Iop_AndV128,
+                                      mkexpr(t2),
+                                      getWReg(wt)),
+                                mkU8(7)));
+               putWReg(wd, binop(Iop_QAdd8Sx16,
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t3)),
+                                             mkexpr(t1)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t1)),
+                                             mkexpr(t3))),
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t4)),
+                                             mkexpr(t2)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t2)),
+                                             mkexpr(t4)))));
+               break;
+            }
 
-               case 0x02: { /* SRAI.W */
-                     DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* ADDS_A.H */
+               DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+               assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+               assign(t3, binop(Iop_SarN16x8,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                mkU8(15)));
+               assign(t4, binop(Iop_SarN16x8,
+                                binop(Iop_AndV128,
+                                      mkexpr(t2),
+                                      getWReg(wt)),
+                                mkU8(15)));
+               putWReg(wd, binop(Iop_QAdd16Sx8,
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t3)),
+                                             mkexpr(t1)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t1)),
+                                             mkexpr(t3))),
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t4)),
+                                             mkexpr(t2)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t2)),
+                                             mkexpr(t4)))));
+               break;
+            }
 
-               case 0x03: { /* SRAI.D */
-                     DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* ADDS_A.W */
+               DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+               assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+               assign(t3, binop(Iop_SarN32x4,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                mkU8(31)));
+               assign(t4, binop(Iop_SarN32x4,
+                                binop(Iop_AndV128,
+                                      mkexpr(t2),
+                                      getWReg(wt)),
+                                mkU8(31)));
+               putWReg(wd, binop(Iop_QAdd32Sx4,
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t3)),
+                                             mkexpr(t1)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t1)),
+                                             mkexpr(t3))),
+                                 binop(Iop_OrV128,
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t4)),
+                                             mkexpr(t2)),
+                                       binop(Iop_AndV128,
+                                             unop(Iop_NotV128,
+                                                  mkexpr(t2)),
+                                             mkexpr(t4)))));
+               break;
             }
 
-            break;
+            case 0x03: { /* ADDS_A.D */
+               DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+               assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+               assign(t3, binop(Iop_SarN64x2,
+                                binop(Iop_AndV128,
+                                      mkexpr(t1),
+                                      getWReg(ws)),
+                                mkU8(63)));
+               assign(t4, binop(Iop_SarN64x2,
+                                binop(Iop_AndV128,
+                                      mkexpr(t2),
+                                      getWReg(wt)),
+                                mkU8(63)));
+               putWReg(wd,
+                       binop(Iop_QAdd64Sx2,
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              mkexpr(t3)),
+                                         mkexpr(t1)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              mkexpr(t1)),
+                                         mkexpr(t3))),
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              mkexpr(t4)),
+                                         mkexpr(t2)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              mkexpr(t2)),
+                                         mkexpr(t4)))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x02: { /* SRLI.df */
-            switch (df) {
-               case 0x00: { /* SRLI.B */
-                     DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* SRLI.H */
-                     DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+      case 0x02: { /* ADDS_S.df */
+         switch (df) {
+            case 0x00: { /* ADDS_S.B */
+               DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* SRLI.W */
-                     DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* ADDS_S.H */
+               DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* SRLI.D */
-                     DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
-                     putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* ADDS_S.W */
+               DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
-         }
+            case 0x03: { /* ADDS_S.D */
+               DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-      case 0x03: { /* BCLRI.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
+            default:
+               return -1;
+         }
 
-            switch (df) {
-               case 0x00: { /* BCLRI.B */
-                     DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2, binop(Iop_ShlN8x16,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)),mkU8(m)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* BCLRI.H */
-                     DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2, binop(Iop_ShlN16x8,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+      case 0x03: { /* ADDS_U.df */
+         switch (df) {
+            case 0x00: { /* ADDS_U.B */
+               DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* BCLRI.W */
-                     DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 32);
-                     assign(t2, binop(Iop_ShlN32x4,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* ADDS_U.H */
+               DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* BCLRI.D */
-                     DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
-                     assign(t2, binop(Iop_ShlN64x2,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* ADDS_U.W */
+               DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            assign(t3, binop(Iop_AndV128,
-                             mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
-            putWReg(wd, mkexpr(t3));
-            break;
+            case 0x03: { /* ADDS_U.D */
+               DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x04: { /* BSETI */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* BSETI.B */
-                     DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2, binop(Iop_ShlN8x16,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+      case 0x04: { /* AVE_S.df */
+         switch (df) {
+            case 0x00: { /* AVE_S.B */
+               DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add8x16,
+                                binop(Iop_Add8x16,
+                                      binop(Iop_SarN8x16,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_SarN8x16,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN8x16,
+                                      binop(Iop_ShlN8x16,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(7)),
+                                      mkU8(7))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* BSETI.H */
-                     DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2, binop(Iop_ShlN16x8,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* AVE_S.H */
+               DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add16x8,
+                            binop(Iop_Add16x8,
+                                  binop(Iop_SarN16x8,
+                                        mkexpr(t1), mkU8(1)),
+                                  binop(Iop_SarN16x8,
+                                        mkexpr(t2), mkU8(1))),
+                            binop(Iop_ShrN16x8,
+                                  binop(Iop_ShlN16x8,
+                                        binop(Iop_AndV128,
+                                              mkexpr(t1),
+                                              mkexpr(t2)),
+                                        mkU8(15)),
+                                  mkU8(15))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* BSETI.W */
-                     DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 32);
-                     assign(t2, binop(Iop_ShlN32x4,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* AVE_S.W */
+               DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add32x4,
+                                binop(Iop_Add32x4,
+                                      binop(Iop_SarN32x4,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_SarN32x4,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN32x4,
+                                      binop(Iop_ShlN32x4,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(31)),
+                                      mkU8(31))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* BSETI.D */
-                     DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
-                     assign(t2, binop(Iop_ShlN64x2,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x03: { /* AVE_S.D */
+               DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add64x2,
+                                binop(Iop_Add64x2,
+                                      binop(Iop_SarN64x2,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_SarN64x2,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN64x2,
+                                      binop(Iop_ShlN64x2,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(63)),
+                                      mkU8(63))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* BNEGI.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* BNEGI.B */
-                     DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2, binop(Iop_ShlN8x16,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+      case 0x05: { /* AVE_U.df */
+         switch (df) {
+            case 0x00: { /* AVE_U.B */
+               DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add16x8,
+                                binop(Iop_Add8x16,
+                                      binop(Iop_ShrN8x16,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_ShrN8x16,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN8x16,
+                                      binop(Iop_ShlN8x16,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(7)),
+                                      mkU8(7))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* BNEGI.H */
-                     DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2, binop(Iop_ShlN16x8,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x01: { /* AVE_U.H */
+               DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add16x8,
+                                binop(Iop_Add16x8,
+                                      binop(Iop_ShrN16x8,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_ShrN16x8,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN16x8,
+                                      binop(Iop_ShlN16x8,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(15)),
+                                      mkU8(15))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* BNEGI.W */
-                     DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
-                     tmp |= (tmp << 32);
-                     assign(t2, binop(Iop_ShlN32x4,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x02: { /* AVE_U.W */
+               DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add32x4,
+                                binop(Iop_Add32x4,
+                                      binop(Iop_ShrN32x4,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_ShrN32x4,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN32x4,
+                                      binop(Iop_ShlN32x4,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(31)),
+                                      mkU8(31))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* BNEGI.D */
-                     DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
-                     assign(t2, binop(Iop_ShlN64x2,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     break;
-                  }
+            case 0x03: { /* AVE_U.D */
+               DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add64x2,
+                                binop(Iop_Add64x2,
+                                      binop(Iop_ShrN64x2,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_ShrN64x2,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN64x2,
+                                      binop(Iop_ShlN64x2,
+                                            binop(Iop_AndV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(63)),
+                                      mkU8(63))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
+            default:
+               return -1;
          }
 
-      case 0x06: { /* BINSLI.df */
-            switch (df) {
-               case 0x00: { /* BINSLI.B */
-                     DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8080808080808080ULL;
-                     assign(t1, binop(Iop_SarN8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* BINSLI.H */
-                     DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000800080008000ULL;
-                     assign(t1,
-                            binop(Iop_SarN16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+      case 0x06: { /* AVER_S.df */
+         switch (df) {
+            case 0x00: { /* AVER_S.B */
+               DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* BINSLI.W */
-                     DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000000080000000ULL;
-                     assign(t1,
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            case 0x01: { /* AVER_S.H */
+               DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* BINSLI.D */
-                     DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000000000000000ULL;
-                     assign(t1,
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            case 0x02: { /* AVER_S.W */
+               DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* AVER_S.D */
+               DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add64x2,
+                                binop(Iop_Add64x2,
+                                      binop(Iop_SarN64x2,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_SarN64x2,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN64x2,
+                                      binop(Iop_ShlN64x2,
+                                            binop(Iop_OrV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(63)),
+                                      mkU8(63))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x07: {
-            switch (df) {
-               case 0x00: { /* BINSRI.B */
-                     DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
-                     assign(t1,
-                            binop(Iop_ShlN8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)), mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* BINSRI.H */
-                     DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
-                     assign(t1,
-                            binop(Iop_ShlN16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+      case 0x07: { /* AVER_U.df */
+         switch (df) {
+            case 0x00: { /* AVER_U.B */
+               DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* BINSRI.W */
-                     DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
-                     assign(t1,
-                            binop(Iop_ShlN32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            case 0x01: { /* AVER_U.H */
+               DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* BINSRI.D */
-                     DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = -2;
-                     assign(t1,
-                            binop(Iop_ShlN64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            case 0x02: { /* AVER_U.W */
+               DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* AVER_U.D */
+               DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_Add64x2,
+                                binop(Iop_Add64x2,
+                                      binop(Iop_ShrN64x2,
+                                            mkexpr(t1), mkU8(1)),
+                                      binop(Iop_ShrN64x2,
+                                            mkexpr(t2), mkU8(1))),
+                                binop(Iop_ShrN64x2,
+                                      binop(Iop_ShlN64x2,
+                                            binop(Iop_OrV128,
+                                                  mkexpr(t1),
+                                                  mkexpr(t2)),
+                                            mkU8(63)),
+                                      mkU8(63))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -14213,498 +7713,682 @@ static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) { /* BIT (0x09) */
    return 0;
 }
 
-static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) { /* BIT (0x0A) */
-   IRTemp t1, t2;
+static Int msa_3R_11(UInt cins, UChar wd, UChar ws)   /* 3R (0x11) */
+{
+   IRTemp t1, t2, t3;
    UShort operation;
-   UChar df, m;
+   UChar df, wt;
 
    operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x007F0000) >> 16;
-
-   if ((df & 0x70) == 0x70) {        // 111mmmm; b
-      m = df & 0x07;
-      df = 0;
-   } else if ((df & 0x60) == 0x60) { // 110mmmm; h
-      m = df & 0x0F;
-      df = 1;
-   } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
-      m = df & 0x1F;
-      df = 2;
-   } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
-      m = df & 0x3F;
-      df = 3;
-   }
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* SAT_S.df */
-            switch (df) {
-               case 0x00: { /* SAT_S.B */
-                     DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
-
-                     if (m == 0) {
-                        putWReg(wd, mkexpr(t1));
-                     } else {
-                        t2 = newTemp(Ity_V128);
-                        assign(t2,
-                               binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_OrV128,
-                                            binop(Iop_AndV128,
-                                                  binop(Iop_CmpEQ8x16,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  getWReg(ws)),
-                                            binop(Iop_ShlN8x16,
-                                                  binop(Iop_CmpGT8Sx16,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(m))),
-                                      binop(Iop_ShrN8x16,
-                                            binop(Iop_CmpGT8Sx16,
-                                                  mkexpr(t2),
-                                                  mkexpr(t1)),
-                                            mkU8(8 - m))));
-                     }
-
-                     break;
-                  }
-
-               case 0x01: { /* SAT_S.H */
-                     DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
-
-                     if (m == 0) {
-                        putWReg(wd, mkexpr(t1));
-                     } else {
-                        t2 = newTemp(Ity_V128);
-                        assign(t2,
-                               binop(Iop_SarN16x8,
-                                     getWReg(ws),
-                                     mkU8(m)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_OrV128,
-                                            binop(Iop_AndV128,
-                                                  binop(Iop_CmpEQ16x8,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  getWReg(ws)),
-                                            binop(Iop_ShlN16x8,
-                                                  binop(Iop_CmpGT16Sx8,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(m))),
-                                      binop(Iop_ShrN16x8,
-                                            binop(Iop_CmpGT16Sx8,
-                                                  mkexpr(t2),
-                                                  mkexpr(t1)),
-                                            mkU8(16 - m))));
-                     }
-
-                     break;
-                  }
-
-               case 0x02: { /* SAT_S.W */
-                     DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
-
-                     if (m == 0) {
-                        putWReg(wd, mkexpr(t1));
-                     } else {
-                        t2 = newTemp(Ity_V128);
-                        assign(t2,
-                               binop(Iop_SarN32x4,
-                                     getWReg(ws),
-                                     mkU8(m)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_OrV128,
-                                            binop(Iop_AndV128,
-                                                  binop(Iop_CmpEQ32x4,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  getWReg(ws)),
-                                            binop(Iop_ShlN32x4,
-                                                  binop(Iop_CmpGT32Sx4,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(m))),
-                                      binop(Iop_ShrN32x4,
-                                            binop(Iop_CmpGT32Sx4,
-                                                  mkexpr(t2),
-                                                  mkexpr(t1)),
-                                            mkU8(32 - m))));
-                     }
-
-                     break;
-                  }
+      case 0x00: { /* SUBS_S.df */
+         switch (df) {
+            case 0x00: { /* SUBS_S.B */
+               DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* SAT_S.D */
-                     DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+            case 0x01: { /* SUBS_S.H */
+               DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     if (m == 0) {
-                        putWReg(wd, mkexpr(t1));
-                     } else {
-                        t2 = newTemp(Ity_V128);
-                        assign(t2,
-                               binop(Iop_SarN64x2,
-                                     getWReg(ws),
-                                     mkU8(m)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_OrV128,
-                                            binop(Iop_AndV128,
-                                                  binop(Iop_CmpEQ64x2,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  getWReg(ws)),
-                                            binop(Iop_ShlN64x2,
-                                                  binop(Iop_CmpGT64Sx2,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(m))),
-                                      binop(Iop_ShrN64x2,
-                                            binop(Iop_CmpGT64Sx2,
-                                                  mkexpr(t2),
-                                                  mkexpr(t1)),
-                                            mkU8(64 - m))));
-                     }
+            case 0x02: { /* SUBS_S.W */
+               DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     break;
-                  }
+            case 0x03: { /* SUBS_S.D */
+               DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x01: { /* SAT_U.df */
-            switch (df) {
-               case 0x00: { /* SAT_U.B */
-                     DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
-
-                     if (m == 7) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_CmpEQ8x16,
-                                     binop(Iop_ShrN8x16,
-                                           getWReg(ws),
-                                           mkU8(m + 1)),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0), mkU64(0))));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      binop(Iop_ShrN8x16,
-                                            unop(Iop_NotV128,
-                                                 mkexpr(t1)),
-                                            mkU8(7 - m))));
-                     }
-
-                     break;
-                  }
-
-               case 0x01: { /* SAT_U.H */
-                     DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
-
-                     if (m == 15) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_CmpEQ16x8,
-                                     binop(Iop_ShrN16x8,
-                                           getWReg(ws),
-                                           mkU8(m + 1)),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0), mkU64(0))));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      binop(Iop_ShrN16x8,
-                                            unop(Iop_NotV128,
-                                                 mkexpr(t1)),
-                                            mkU8(15 - m))));
-                     }
+         break;
+      }
 
-                     break;
-                  }
+      case 0x01: { /* SUBS_U.df */
+         switch (df) {
+            case 0x00: { /* SUBS_U.B */
+               DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* SAT_U.W */
-                     DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
+            case 0x01: { /* SUBS_U.H */
+               DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     if (m == 31) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_CmpEQ32x4,
-                                     binop(Iop_ShrN32x4,
-                                           getWReg(ws),
-                                           mkU8(m + 1)),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0), mkU64(0))));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1), \
-                                            getWReg(ws)),
-                                      binop(Iop_ShrN32x4,
-                                            unop(Iop_NotV128,
-                                                 mkexpr(t1)),
-                                            mkU8(31 - m))));
-                     }
+            case 0x02: { /* SUBS_U.W */
+               DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     break;
-                  }
+            case 0x03: { /* SUBS_U.D */
+               DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* SAT_U.D */
-                     DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
+            default:
+               return -1;
+         }
 
-                     if (m == 63) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_CmpEQ64x2,
-                                     binop(Iop_ShrN64x2,
-                                           getWReg(ws),
-                                           mkU8(m + 1)),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0), mkU64(0))));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      binop(Iop_ShrN64x2,
-                                            unop(Iop_NotV128,
-                                                 mkexpr(t1)),
-                                            mkU8(63 - m))));
-                     }
+         break;
+      }
 
-                     break;
-                  }
+      case 0x02: { /* SUBSUS_U.df */
+         switch (df) {
+            case 0x00: { /* SUBSUS_U.B */
+               DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+               assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
+               assign(t3, binop(Iop_OrV128,
+                                binop(Iop_CmpGT8Ux16,
+                                      getWReg(ws),
+                                      getWReg(wt)),
+                                binop(Iop_CmpEQ8x16,
+                                      getWReg(ws),
+                                      getWReg(wt))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t3),
+                                         mkexpr(t2)))));
+               break;
             }
 
-            break;
-         }
+            case 0x01: { /* SUBSUS_U.H */
+               DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+               assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
+               assign(t3,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpGT16Ux8,
+                                  getWReg(ws),
+                                  getWReg(wt)),
+                            binop(Iop_CmpEQ16x8,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t3),
+                                         mkexpr(t2)))));
+               break;
+            }
 
-      case 0x02: { /* SRARI.df */
-            switch (df) {
-               case 0x00: { /* SRARI.B */
-                     DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_SarN8x16,
+            case 0x02: { /* SUBSUS_U.W */
+               DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+               assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
+               assign(t3,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpGT32Ux4,
                                   getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN8x16,
-                                  binop(Iop_ShlN8x16,
-                                        getWReg(ws),
-                                        mkU8(8 - m)),
-                                  mkU8(7)));
+                                  getWReg(wt)),
+                            binop(Iop_CmpEQ32x4,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t3),
+                                         mkexpr(t2)))));
+               break;
+            }
 
-                     if (m) putWReg(wd, binop(Iop_Add8x16,
-                                              mkexpr(t1),
-                                              mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+            case 0x03: { /* SUBSUS_U.D */
+               DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+               assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
+               assign(t3,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpGT64Ux2,
+                                  getWReg(ws),
+                                  getWReg(wt)),
+                            binop(Iop_CmpEQ64x2,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t3),
+                                         mkexpr(t2)))));
+               break;
+            }
 
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x01: { /* SRARI.H */
-                     DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_SarN16x8,
-                                  getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN16x8,
-                                  binop(Iop_ShlN16x8,
-                                        getWReg(ws),
-                                        mkU8(16 - m)),
-                                  mkU8(15)));
+         break;
+      }
 
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add16x8,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+      case 0x03: { /* SUBSUU_S.df */
+         switch (df) {
+            case 0x00: { /* SUBSUU_S.B */
+               DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+               assign(t2,
+                      binop(Iop_SarN8x16,
+                            binop (Iop_AndV128,
+                                   binop(Iop_XorV128,
+                                         getWReg(ws),
+                                         getWReg(wt)),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t1),
+                                         getWReg(wt))),
+                            mkU8(7)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            binop(Iop_SarN8x16,
+                                  getWReg(ws), mkU8(7)),
+                            mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   unop(Iop_NotV128,
+                                        mkexpr(t2))),
+                             binop(Iop_XorV128,
+                                   binop(Iop_ShlN8x16,
+                                         mkexpr(t2), mkU8(7)),
+                                   mkexpr(t3))));
+               break;
+            }
 
-                     break;
-                  }
+            case 0x01: { /* SUBSUU_S.H */
+               DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+               assign(t2,
+                      binop(Iop_SarN16x8,
+                            binop (Iop_AndV128,
+                                   binop(Iop_XorV128,
+                                         getWReg(ws),
+                                         getWReg(wt)),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t1),
+                                         getWReg(wt))),
+                            mkU8(15)));
+               assign(t3,
+                      binop(Iop_AndV128,
+                            binop(Iop_SarN16x8,
+                                  getWReg(ws),
+                                  mkU8(15)),
+                            mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   unop(Iop_NotV128,
+                                        mkexpr(t2))),
+                             binop(Iop_XorV128,
+                                   binop(Iop_ShlN16x8,
+                                         mkexpr(t2), mkU8(15)),
+                                   mkexpr(t3))));
+               break;
+            }
 
-               case 0x02: { /* SRARI.W */
-                     DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
+            case 0x02: { /* SUBSUU_S.W */
+               DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+               assign(t2,
+                      binop(Iop_SarN32x4,
+                            binop (Iop_AndV128,
+                                   binop(Iop_XorV128,
+                                         getWReg(ws),
+                                         getWReg(wt)),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t1),
+                                         getWReg(wt))),
+                            mkU8(31)));
+               assign(t3,
+                      binop(Iop_AndV128,
                             binop(Iop_SarN32x4,
                                   getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN32x4,
-                                  binop(Iop_ShlN32x4,
-                                        getWReg(ws),
-                                        mkU8(32 - m)),
-                                  mkU8(31)));
-
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add32x4,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
-
-                     break;
-                  }
+                                  mkU8(31)),
+                            mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   unop(Iop_NotV128,
+                                        mkexpr(t2))),
+                             binop(Iop_XorV128,
+                                   binop(Iop_ShlN32x4,
+                                         mkexpr(t2),
+                                         mkU8(31)),
+                                   mkexpr(t3))));
+               break;
+            }
 
-               case 0x03: { /* SRARI.D */
-                     DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
+            case 0x03: { /* SUBSUU_S.D */
+               DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+               assign(t2,
+                      binop(Iop_SarN64x2,
+                            binop (Iop_AndV128,
+                                   binop(Iop_XorV128,
+                                         getWReg(ws),
+                                         getWReg(wt)),
+                                   binop(Iop_XorV128,
+                                         mkexpr(t1),
+                                         getWReg(wt))),
+                            mkU8(63)));
+               assign(t3,
+                      binop(Iop_AndV128,
                             binop(Iop_SarN64x2,
                                   getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN64x2,
-                                  binop(Iop_ShlN64x2,
-                                        getWReg(ws),
-                                        mkU8(64 - m)),
-                                  mkU8(63)));
-
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add64x2,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
-
-                     break;
-                  }
+                                  mkU8(63)),
+                            mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t1),
+                                   unop(Iop_NotV128,
+                                        mkexpr(t2))),
+                             binop(Iop_XorV128,
+                                   binop(Iop_ShlN64x2,
+                                         mkexpr(t2), mkU8(63)),
+                                   mkexpr(t3))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* SRLRI.df */
-            switch (df) {
-               case 0x00: { /* SRLRI.B */
-                     DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_ShrN8x16,
-                                  getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN8x16,
-                                  binop(Iop_ShlN8x16,
-                                        getWReg(ws),
-                                        mkU8(8 - m)),
-                                  mkU8(7)));
-
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add8x16,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+         break;
+      }
 
-                     break;
-                  }
+      case 0x04: { /* ASUB_S.df */
+         switch (df) {
+            case 0x00: { /* ASUB_S.B */
+               DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
+               assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
+               assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128,
+                                                    mkexpr(t1)),
+                                               mkexpr(t2)),
+                                         mkexpr(t3)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              binop(Iop_XorV128,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2))),
+                                         unop(Iop_Abs8x16,
+                                              mkexpr(t3)))),
+                             binop(Iop_AndV128,
+                                   binop(Iop_AndV128,
+                                         mkexpr(t1),
+                                         unop(Iop_NotV128,
+                                              mkexpr(t2))),
+                                   binop(Iop_Sub8x16,
+                                         getWReg(wt),
+                                         getWReg(ws)))));
+               break;
+            }
 
-               case 0x01: { /* SRLRI.H */
-                     DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_ShrN16x8,
-                                  getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN16x8,
-                                  binop(Iop_ShlN16x8,
-                                        getWReg(ws),
-                                        mkU8(16 - m)),
-                                  mkU8(15)));
+            case 0x01: { /* ASUB_S.H */
+               DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
+               assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
+               assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128,
+                                                    mkexpr(t1)),
+                                               mkexpr(t2)),
+                                         mkexpr(t3)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              binop(Iop_XorV128,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2))),
+                                         unop(Iop_Abs16x8,
+                                              mkexpr(t3)))),
+                             binop(Iop_AndV128,
+                                   binop(Iop_AndV128,
+                                         mkexpr(t1),
+                                         unop(Iop_NotV128,
+                                              mkexpr(t2))),
+                                   binop(Iop_Sub16x8,
+                                         getWReg(wt),
+                                         getWReg(ws)))));
+               break;
+            }
 
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add16x8,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+            case 0x02: { /* ASUB_S.W */
+               DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
+               assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
+               assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128,
+                                                    mkexpr(t1)),
+                                               mkexpr(t2)),
+                                         mkexpr(t3)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              binop(Iop_XorV128,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2))),
+                                         unop(Iop_Abs32x4,
+                                              mkexpr(t3)))),
+                             binop(Iop_AndV128,
+                                   binop(Iop_AndV128,
+                                         mkexpr(t1),
+                                         unop(Iop_NotV128,
+                                              mkexpr(t2))),
+                                   binop(Iop_Sub32x4,
+                                         getWReg(wt),
+                                         getWReg(ws)))));
+               break;
+            }
 
-                     break;
-                  }
+            case 0x03: { /* ASUB_S.D */
+               DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+               assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
+               assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_OrV128,
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128,
+                                                    mkexpr(t1)),
+                                               mkexpr(t2)),
+                                         mkexpr(t3)),
+                                   binop(Iop_AndV128,
+                                         unop(Iop_NotV128,
+                                              binop(Iop_XorV128,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2))),
+                                         unop(Iop_Abs64x2,
+                                              mkexpr(t3)))),
+                             binop(Iop_AndV128,
+                                   binop(Iop_AndV128,
+                                         mkexpr(t1),
+                                         unop(Iop_NotV128,
+                                              mkexpr(t2))),
+                                   binop(Iop_Sub64x2,
+                                         getWReg(wt),
+                                         getWReg(ws)))));
+               break;
+            }
 
-               case 0x02: { /* SRLRI.W */
-                     DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_ShrN32x4,
-                                  getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN32x4,
-                                  binop(Iop_ShlN32x4,
-                                        getWReg(ws),
-                                        mkU8(32 - m)),
-                                  mkU8(31)));
+            default:
+               return -1;
+         }
 
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add32x4,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+         break;
+      }
 
-                     break;
-                  }
+      case 0x05: { /* ASUB_U.df */
+         switch (df) {
+            case 0x00: { /* ASUB_U.B */
+               DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_SarN8x16,
+                            binop(Iop_XorV128,
+                                  mkexpr(t1), mkexpr(t2)),
+                            mkU8(7)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128, mkexpr(t3)),
+                                   unop(Iop_Abs8x16,
+                                        binop(Iop_Sub8x16,
+                                              mkexpr(t1),
+                                              mkexpr(t2)))),
+                             binop(Iop_AndV128, mkexpr(t3),
+                                   binop(Iop_Sub8x16,
+                                         binop(Iop_Max8Ux16,
+                                               mkexpr(t1),
+                                               mkexpr(t2)),
+                                         binop(Iop_Min8Ux16,
+                                               mkexpr(t1),
+                                               mkexpr(t2))))));
+               break;
+            }
 
-               case 0x03: { /* SRLRI.D */
-                     DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_ShrN64x2,
-                                  getWReg(ws),
-                                  mkU8(m)));
-                     assign(t2,
-                            binop(Iop_ShrN64x2,
-                                  binop(Iop_ShlN64x2,
-                                        getWReg(ws),
-                                        mkU8(64 - m)),
-                                  mkU8(63)));
+            case 0x01: { /* ASUB_U.H */
+               DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_SarN16x8,
+                            binop(Iop_XorV128,
+                                  mkexpr(t1), mkexpr(t2)),
+                            mkU8(15)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128,
+                                        mkexpr(t3)),
+                                   unop(Iop_Abs16x8,
+                                        binop(Iop_Sub16x8,
+                                              mkexpr(t1),
+                                              mkexpr(t2)))),
+                             binop(Iop_AndV128,
+                                   mkexpr(t3),
+                                   binop(Iop_Sub16x8,
+                                         binop(Iop_Max16Ux8,
+                                               mkexpr(t1),
+                                               mkexpr(t2)),
+                                         binop(Iop_Min16Ux8,
+                                               mkexpr(t1),
+                                               mkexpr(t2))))));
+               break;
+            }
 
-                     if (m)
-                        putWReg(wd,
-                                binop(Iop_Add64x2,
-                                      mkexpr(t1), mkexpr(t2)));
-                     else putWReg(wd, mkexpr(t1));
+            case 0x02: { /* ASUB_U.W */
+               DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_SarN32x4,
+                            binop(Iop_XorV128,
+                                  mkexpr(t1), mkexpr(t2)),
+                            mkU8(31)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128, mkexpr(t3)),
+                                   unop(Iop_Abs32x4,
+                                        binop(Iop_Sub32x4,
+                                              mkexpr(t1),
+                                              mkexpr(t2)))),
+                             binop(Iop_AndV128,
+                                   mkexpr(t3),
+                                   binop(Iop_Sub32x4,
+                                         binop(Iop_Max32Ux4,
+                                               mkexpr(t1),
+                                               mkexpr(t2)),
+                                         binop(Iop_Min32Ux4,
+                                               mkexpr(t1),
+                                               mkexpr(t2))))));
+               break;
+            }
 
-                     break;
-                  }
+            case 0x03: { /* ASUB_U.D */
+               DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_SarN64x2,
+                            binop(Iop_XorV128,
+                                  mkexpr(t1), mkexpr(t2)),
+                            mkU8(63)));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128, mkexpr(t3)),
+                                   unop(Iop_Abs64x2,
+                                        binop(Iop_Sub64x2,
+                                              mkexpr(t1),
+                                              mkexpr(t2)))),
+                             binop(Iop_AndV128,
+                                   mkexpr(t3),
+                                   binop(Iop_Sub64x2,
+                                         binop(Iop_Max64Ux2,
+                                               mkexpr(t1),
+                                               mkexpr(t2)),
+                                         binop(Iop_Min64Ux2,
+                                               mkexpr(t1),
+                                               mkexpr(t2))))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -14712,8 +8396,9 @@ static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) { /* BIT (0x0A) */
    return 0;
 }
 
-static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) { /* 3R (0x0D) */
-   IRTemp t1, t2, t3;
+static Int msa_3R_12(UInt cins, UChar wd, UChar ws)   /* 3R (0x12) */
+{
+   IRTemp t1, t2, t3, t4, t5, t6;
    UShort operation;
    UChar df, wt;
 
@@ -14722,1453 +8407,1644 @@ static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) { /* 3R (0x0D) */
    wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* SLL.df */
-            switch (df) {
-               case 0x00: { /* SLL.B */
-                     DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* SLL.H */
-                     DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x02: { /* SLL.W */
-                     DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x03: { /* SLL.D */
-                     DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               default:
-                  return -1;
+      case 0x00: { /* MULV.df */
+         switch (df) {
+            case 0x00: { /* MULV.B */
+               DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
+               break;
             }
 
-            break;
-         }
-
-      case 0x01: { /* SRA.df */
-            switch (df) {
-               case 0x00: { /* SRA.B */
-                     DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* SRA.H */
-                     DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x02: { /* SRA.W */
-                     DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MULV.H */
+               DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* SRA.D */
-                     DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MULV.W */
+               DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* MULV.D */
+               DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_Mul64,
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t2))),
+                             binop(Iop_Mul64,
+                                   unop(Iop_V128to64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128to64,
+                                        mkexpr(t2)))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* SRL.df */
-            switch (df) {
-               case 0x00: { /* SRL.B */
-                     DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* SRL.H */
-                     DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x01: { /* MADDV.df */
+         switch (df) {
+            case 0x00: { /* MADDV.B */
+               DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Add8x16,
+                             getWReg(wd),
+                             binop(Iop_Mul8x16,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               case 0x02: { /* SRL.W */
-                     DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MADDV.H */
+               DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Add16x8,
+                             getWReg(wd),
+                             binop(Iop_Mul16x8,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               case 0x03: { /* SRL.D */
-                     DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MADDV.W */
+               DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Add32x4,
+                             getWReg(wd),
+                             binop(Iop_Mul32x4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* MADDV.D */
+               DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               putWReg(wd,
+                       binop(Iop_Add64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_Mul64,
+                                         unop(Iop_V128HIto64,
+                                              mkexpr(t1)),
+                                         unop(Iop_V128HIto64,
+                                              mkexpr(t2))),
+                                   binop(Iop_Mul64,
+                                         unop(Iop_V128to64,
+                                              mkexpr(t1)),
+                                         unop(Iop_V128to64,
+                                              mkexpr(t2))))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* BCLR.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* BCLR.B */
-                     DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2, binop(Iop_Shl8x16,
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(tmp), mkU64(tmp)),
-                                      getWReg(wt)));
-                     break;
-                  }
+      case 0x02: { /* MSUBV.df */
+         switch (df) {
+            case 0x00: { /* MSUBV.B */
+               DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Sub8x16,
+                             getWReg(wd),
+                             binop(Iop_Mul8x16,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               case 0x01: { /* BCLR.H */
-                     DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2,
-                            binop(Iop_Shl16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+            case 0x01: { /* MSUBV.H */
+               DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Sub16x8,
+                             getWReg(wd),
+                             binop(Iop_Mul16x8,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               case 0x02: { /* BCLR.W */
-                     DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 32);
-                     assign(t2,
-                            binop(Iop_Shl32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+            case 0x02: { /* MSUBV.W */
+               DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_Sub32x4,
+                             getWReg(wd),
+                             binop(Iop_Mul32x4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               case 0x03: { /* BCLR.D */
-                     DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
-                     assign(t2,
-                            binop(Iop_Shl64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+            case 0x03: { /* MSUBV.D */
+               DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               putWReg(wd,
+                       binop(Iop_Sub64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_Mul64,
+                                         unop(Iop_V128HIto64,
+                                              mkexpr(t1)),
+                                         unop(Iop_V128HIto64,
+                                              mkexpr(t2))),
+                                   binop(Iop_Mul64,
+                                         unop(Iop_V128to64,
+                                              mkexpr(t1)),
+                                         unop(Iop_V128to64,
+                                              mkexpr(t2))))));
+               break;
             }
 
-            assign(t3,
-                   binop(Iop_AndV128,
-                         mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
-            putWReg(wd, mkexpr(t3));
-            break;
+            default:
+               return -1;
          }
 
-      case 0x04: { /* BSET.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
-
-            switch (df) {
-               case 0x00: { /* BSET.B */
-                     DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2,
-                            binop(Iop_Shl8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* BSET.H */
-                     DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2,
-                            binop(Iop_Shl16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+      case 0x04: { /* DIV_S.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x02: { /* BSET.W */
-                     DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 32);
-                     assign(t2,
-                            binop(Iop_Shl32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: { /* DIV_S.B */
+               DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[16];
+               Int i;
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFF),
+                                     binop(Iop_DivS32,
+                                           unop(Iop_8Sto32,
+                                                binop(Iop_GetElem8x16,
+                                                      mkexpr(t1),
+                                                      mkU8(i))),
+                                           unop(Iop_8Sto32,
+                                                binop(Iop_GetElem8x16,
+                                                      mkexpr(t2),
+                                                      mkU8(i))))),
+                               mkU8((i & 3) << 3)));
+               }
 
-               case 0x03: { /* BSET.D */
-                     DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
-                     assign(t2,
-                            binop(Iop_Shl64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[15]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[14]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[13]),
+                                                     mkexpr(tmp[12])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[11]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[10]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[9]),
+                                                     mkexpr(tmp[8]))))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[6]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[5]),
+                                                     mkexpr(tmp[4])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[2]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0]))))))
+                      );
+               break;
             }
 
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+            case 0x01: { /* DIV_S.H */
+               DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
 
-      case 0x05: { /* BNEG.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            ULong tmp = 1;
-            assign(t1, getWReg(ws));
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFFFF),
+                                     binop(Iop_DivS32,
+                                           unop(Iop_16Sto32,
+                                                binop(Iop_GetElem16x8,
+                                                      mkexpr(t1),
+                                                      mkU8(i))),
+                                           unop(Iop_16Sto32,
+                                                binop(Iop_GetElem16x8,
+                                                      mkexpr(t2),
+                                                      mkU8(i))))),
+                               mkU8((i & 1) << 4)));
+               }
 
-            switch (df) {
-               case 0x00: { /* BNEG.B */
-                     DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
-                            (tmp << 32) | (tmp << 24) | (tmp << 16) |
-                            (tmp << 8);
-                     assign(t2,
-                            binop(Iop_Shl8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x01: { /* BNEG.H */
-                     DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
-                     assign(t2,
-                            binop(Iop_Shl16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+            case 0x02: { /* DIV_S.W */
+               DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-               case 0x02: { /* BNEG.W */
-                     DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
-                     tmp |= (tmp << 32);
-                     assign(t2,
-                            binop(Iop_Shl32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_DivS32,
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t1), mkU8(i)),
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t2), mkU8(i))));
+               }
 
-               case 0x03: { /* BNEG.D */
-                     DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
-                     assign(t2,
-                            binop(Iop_Shl64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128, \
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+            case 0x03: { /* DIV_S.D */
+               DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_DivS64,
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t2))),
+                             binop(Iop_DivS64,
+                                   unop(Iop_V128to64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128to64,
+                                        mkexpr(t2)))));
+               break;
+            }
 
-      case 0x06: { /* BINSL.df */
-            switch (df) {
-               case 0x00: { /* BINSL.B */
-                     DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8080808080808080ULL;
-                     assign(t1,
-                            binop(Iop_Sar8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x01: { /* BINSL.H */
-                     DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000800080008000ULL;
-                     assign(t1,
-                            binop(Iop_Sar16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* BINSL.W */
-                     DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000000080000000ULL;
-                     assign(t1,
-                            binop(Iop_Sar32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+      case 0x05: { /* DIV_U.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x03: { /* BINSL.D */
-                     DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0x8000000000000000ULL;
-                     assign(t1,
-                            binop(Iop_Sar64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(wd)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(ws)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: { /* DIV_U.B */
+               DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[16];
+               Int i;
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFF),
+                                     binop(Iop_DivU32,
+                                           unop(Iop_8Uto32,
+                                                binop(Iop_GetElem8x16,
+                                                      mkexpr(t1),
+                                                      mkU8(i))),
+                                           unop(Iop_8Uto32,
+                                                binop(Iop_GetElem8x16,
+                                                      mkexpr(t2),
+                                                      mkU8(i))))),
+                               mkU8((i & 3) << 3)));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[15]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[14]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[13]),
+                                                     mkexpr(tmp[12])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[11]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[10]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[9]),
+                                                     mkexpr(tmp[8]))))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[6]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[5]),
+                                                     mkexpr(tmp[4])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[2]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0]))))))
+                      );
+               break;
             }
 
-            break;
-         }
+            case 0x01: { /* DIV_U.H */
+               DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
 
-      case 0x07: { /* BINSR.df */
-            switch (df) {
-               case 0x00: { /* BINSR.B */
-                     DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
-                     assign(t1,
-                            binop(Iop_Shl8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFFFF),
+                                     binop(Iop_DivU32,
+                                           unop(Iop_16Uto32,
+                                                binop(Iop_GetElem16x8,
+                                                      mkexpr(t1),
+                                                      mkU8(i))),
+                                           unop(Iop_16Uto32,
+                                                binop(Iop_GetElem16x8,
+                                                      mkexpr(t2),
+                                                      mkU8(i))))),
+                               mkU8((i & 1) << 4)));
+               }
 
-               case 0x01: { /* BINSR.H */
-                     DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
-                     assign(t1,
-                            binop(Iop_Shl16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x02: { /* BINSR.W */
-                     DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
-                     assign(t1,
-                            binop(Iop_Shl32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+            case 0x02: { /* DIV_U.W */
+               DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-               case 0x03: { /* BINSR.D */
-                     DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     ULong tmp = -2;
-                     assign(t1,
-                            binop(Iop_Shl64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(tmp), mkU64(tmp)),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128, mkexpr(t1)),
-                                  getWReg(ws)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  mkexpr(t1), getWReg(wd)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_DivU32,
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t1), mkU8(i)),
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t2), mkU8(i))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
+            case 0x03: { /* DIV_U.D */
+               DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_DivU64,
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128HIto64,
+                                        mkexpr(t2))),
+                             binop(Iop_DivU64,
+                                   unop(Iop_V128to64,
+                                        mkexpr(t1)),
+                                   unop(Iop_V128to64,
+                                        mkexpr(t2)))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
 
-   return 0;
-}
+      case 0x06: { /* MOD_S.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-static Int msa_3R_0E(UInt cins, UChar wd, UChar ws) { /* 3R (0x0E) */
-   IRTemp t1, t2, t3, t4;
-   UShort operation;
-   UChar df, wt;
+         switch (df) {
+            case 0x00: { /* MOD_S.B */
+               DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[16];
+               Int i;
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFF),
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_DivModS32to32,
+                                                unop(Iop_8Sto32,
+                                                     binop(Iop_GetElem8x16,
+                                                           mkexpr(t1),
+                                                           mkU8(i))),
+                                                unop(Iop_8Sto32,
+                                                     binop(Iop_GetElem8x16,
+                                                           mkexpr(t2),
+                                                           mkU8(i)))))),
+                               mkU8((i & 3) << 3)));
+               }
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[15]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[14]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[13]),
+                                                     mkexpr(tmp[12])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[11]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[10]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[9]),
+                                                     mkexpr(tmp[8]))))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[6]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[5]),
+                                                     mkexpr(tmp[4])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[2]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0])))))));
+               break;
+            }
 
-   switch (operation) {
-      case 0x00: { /* ADDV.df */
-            switch (df) {
-               case 0x00: { /* ADDV.B */
-                     DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* MOD_S.H */
+               DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
 
-               case 0x01: { /* ADDV.H */
-                     DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFFFF),
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_DivModS32to32,
+                                                unop(Iop_16Sto32,
+                                                     binop(Iop_GetElem16x8,
+                                                           mkexpr(t1),
+                                                           mkU8(i))),
+                                                unop(Iop_16Sto32,
+                                                     binop(Iop_GetElem16x8,
+                                                           mkexpr(t2),
+                                                           mkU8(i)))))),
+                               mkU8((i & 1) << 4)));
+               }
 
-               case 0x02: { /* ADDV.W */
-                     DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x03: { /* ADDV.D */
-                     DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MOD_S.W */
+               DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         unop(Iop_64HIto32,
+                              binop(Iop_DivModS32to32,
+                                    binop(Iop_GetElem32x4,
+                                          mkexpr(t1),
+                                          mkU8(i)),
+                                    binop(Iop_GetElem32x4,
+                                          mkexpr(t2),
+                                          mkU8(i)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
-         }
+            case 0x03: { /* MOD_S.D */
+               DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I64);
+               t5 = newTemp(Ity_I64);
+               t6 = newTemp(Ity_I64);
+               assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
+               assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
+               assign(t5, unop(Iop_V128to64, mkexpr(t1)));
+               assign(t6, unop(Iop_V128to64, mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_Sub64,
+                                   mkexpr(t3),
+                                   binop(Iop_Mul64,
+                                         mkexpr(t4),
+                                         binop(Iop_DivS64,
+                                               mkexpr(t3),
+                                               mkexpr(t4)))),
+                             binop(Iop_Sub64,
+                                   mkexpr(t5),
+                                   binop(Iop_Mul64,
+                                         mkexpr(t6),
+                                         binop(Iop_DivS64,
+                                               mkexpr(t5),
+                                               mkexpr(t6))))));
+               break;
+            }
 
-      case 0x01: { /* SUBV.df */
-            switch (df) {
-               case 0x00: { /* SUBV.B */
-                     DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x01: { /* SUBV.H */
-                     DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* SUBV.W */
-                     DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x07: { /* MOD_U.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x03: { /* SUBV.D */
-                     DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: { /* MOD_U.B */
+               DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[16];
+               Int i;
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFF),
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_DivModU32to32,
+                                                unop(Iop_8Uto32,
+                                                     binop(Iop_GetElem8x16,
+                                                           mkexpr(t1),
+                                                           mkU8(i))),
+                                                unop(Iop_8Uto32,
+                                                     binop(Iop_GetElem8x16,
+                                                           mkexpr(t2),
+                                                           mkU8(i)))))),
+                               mkU8((i & 3) << 3)));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[15]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[14]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[13]),
+                                                     mkexpr(tmp[12])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[11]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[10]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[9]),
+                                                     mkexpr(tmp[8]))))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[6]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[5]),
+                                                     mkexpr(tmp[4])))),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         binop(Iop_Or32,
+                                               mkexpr(tmp[2]),
+                                               binop(Iop_Or32,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0])))))));
+               break;
             }
 
-            break;
-         }
+            case 0x01: { /* MOD_U.H */
+               DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
 
-      case 0x02: { /* MAX_S.df */
-            switch (df) {
-               case 0x00: { /* MAX_S.B */
-                     DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Shl32,
+                               binop(Iop_And32,
+                                     mkU32(0xFFFF),
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_DivModU32to32,
+                                                unop(Iop_16Uto32,
+                                                     binop(Iop_GetElem16x8,
+                                                           mkexpr(t1),
+                                                           mkU8(i))),
+                                                unop(Iop_16Uto32,
+                                                     binop(Iop_GetElem16x8,
+                                                           mkexpr(t2),
+                                                           mkU8(i)))))),
+                               mkU8((i & 1) << 4)));
+               }
 
-               case 0x01: { /* MAX_S.H */
-                     DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_Or32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x02: { /* MAX_S.W */
-                     DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* MOD_U.W */
+               DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         unop(Iop_64HIto32,
+                              binop(Iop_DivModU32to32,
+                                    binop(Iop_GetElem32x4,
+                                          mkexpr(t1),
+                                          mkU8(i)),
+                                    binop(Iop_GetElem32x4,
+                                          mkexpr(t2),
+                                          mkU8(i)))));
+               }
 
-               case 0x03: { /* MAX_S.D */
-                     DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* MOD_U.D */
+               DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I64);
+               t5 = newTemp(Ity_I64);
+               t6 = newTemp(Ity_I64);
+               assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
+               assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
+               assign(t5, unop(Iop_V128to64, mkexpr(t1)));
+               assign(t6, unop(Iop_V128to64, mkexpr(t2)));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_Sub64,
+                                   mkexpr(t3),
+                                   binop(Iop_Mul64,
+                                         mkexpr(t4),
+                                         binop(Iop_DivU64,
+                                               mkexpr(t3),
+                                               mkexpr(t4)))),
+                             binop(Iop_Sub64,
+                                   mkexpr(t5),
+                                   binop(Iop_Mul64,
+                                         mkexpr(t6),
+                                         binop(Iop_DivU64,
+                                               mkexpr(t5),
+                                               mkexpr(t6))))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* MAX_U.df */
-            switch (df) {
-               case 0x00: { /* MAX_U.B */
-                     DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MAX_U.H */
-                     DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      default:
+         return -1;
+   }
 
-               case 0x02: { /* MAX_U.W */
-                     DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+   return 0;
+}
 
-               case 0x03: { /* MAX_U.D */
-                     DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+static Int msa_3R_13(UInt cins, UChar wd, UChar ws)   /* 3R (0x13) */
+{
+   IRTemp t1, t2;
+   UShort operation;
+   UChar df, wt;
 
-               default:
-                  return -1;
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
+
+   switch (operation) {
+      case 0x00: { /* DOTP_S.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
+
+         switch (df) {
+            case 0x01: { /* DOTP_S.H */
+               DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* DOTP_S.W */
+               DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-      case 0x04: { /* MIN_S.df */
-            switch (df) {
-               case 0x00: { /* MIN_S.B */
-                     DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x01: { /* MIN_S.H */
-                     DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
 
-               case 0x02: { /* MIN_S.W */
-                     DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* DOTP_S.D */
+               DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x03: { /* MIN_S.D */
-                     DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(tmp[1]), mkexpr(tmp[0])));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* MIN_U.df */
-            switch (df) {
-               case 0x00: { /* MIN_U.B */
-                     DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* MIN_U.H */
-                     DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* MIN_U.W */
-                     DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x01: { /* DOTP_U.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x03: { /* MIN_U.D */
-                     DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x01: { /* DOTP_U.H */
+               DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* DOTP_U.W */
+               DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-      case 0x06: { /* MAX_A.df */
-            switch (df) {
-               case 0x00: { /* MAX_A.B */
-                     DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
-                     assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(ws)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(wt))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x01: { /* MAX_A.H */
-                     DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
-                     assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(ws)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(wt))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
 
-               case 0x02: { /* MAX_A.W */
-                     DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
-                     assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(ws)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(wt))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* DOTP_U.D */
+               DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x03: { /* MAX_A.D */
-                     DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
-                     assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(ws)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(wt))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(tmp[1]), mkexpr(tmp[0])));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x07: { /* MIN_A.df */
-            switch (df) {
-               case 0x00: { /* MIN_A.B */
-                     DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
-                     assign(t4, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT8Ux16,
-                                            mkexpr(t1), mkexpr(t2)),
-                                      binop(Iop_CmpEQ8x16,
-                                            mkexpr(t1), mkexpr(t2))));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(wt)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(ws))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MIN_A.H */
-                     DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
-                     assign(t4, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT16Ux8,
-                                            mkexpr(t1), mkexpr(t2)),
-                                      binop(Iop_CmpEQ16x8,
-                                            mkexpr(t1), mkexpr(t2))));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(wt)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(ws))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x02: { /* DPADD_S.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x02: { /* MIN_A.W */
-                     DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
-                     assign(t4, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT32Ux4,
-                                            mkexpr(t1), mkexpr(t2)),
-                                      binop(Iop_CmpEQ32x4,
-                                            mkexpr(t1), mkexpr(t2))));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(wt)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(ws))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x01: { /* DPADD_S.H */
+               DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x03: { /* MIN_A.D */
-                     DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
-                     assign(t4, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT64Ux2,
-                                            mkexpr(t1), mkexpr(t2)),
-                                      binop(Iop_CmpEQ64x2,
-                                            mkexpr(t1), mkexpr(t2))));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t4),
-                                            getWReg(wt)),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128, mkexpr(t4)),
-                                            getWReg(ws))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_Add16x8,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x02: { /* DPADD_S.W */
+               DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_Add32x4,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
+            case 0x03: { /* DPADD_S.D */
+               DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
+
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_Add64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
 
-   return 0;
-}
+      case 0x03: { /* DPADD_U.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) { /* 3R (0x0F) */
-   IRTemp t1, t2, t3;
-   UShort operation;
-   UChar df, wt;
+         switch (df) {
+            case 0x01: { /* DPADD_U.H */
+               DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+               putWReg(wd,
+                       binop(Iop_Add16x8,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
+            }
 
-   switch (operation) {
-      case 0x00: { /* CEQ.df */
-            switch (df) {
-               case 0x00: { /* CEQ.B */
-                     DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* DPADD_U.W */
+               DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-               case 0x01: { /* CEQ.H */
-                     DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x02: { /* CEQ.W */
-                     DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_Add32x4,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x03: { /* CEQ.D */
-                     DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* DPADD_U.D */
+               DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               default:
-                  return -1;
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_Add64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* CLT_S.df */
-            switch (df) {
-               case 0x00: { /* CLT_S.B */
-                     DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* CLT_S.H */
-                     DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* CLT_S.W */
-                     DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x04: { /* DPSUB_S.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x03: { /* CLT_S.D */
-                     DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x01: { /* DPSUB_S.H */
+               DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_Sub16x8,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* DPSUB_S.W */
+               DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-      case 0x03: { /* CLT_U.df */
-            switch (df) {
-               case 0x00: { /* CLT_U.B */
-                     DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x01: { /* CLT_U.H */
-                     DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_Sub32x4,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x02: { /* CLT_U.W */
-                     DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* DPSUB_S.D */
+               DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x03: { /* CLT_U.D */
-                     DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullS32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_Sub64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x04: { /* CLE_S.df */
-            switch (df) {
-               case 0x00: { /* CLE_S.B */
-                     DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT8Sx16,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ8x16,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* CLE_S.H */
-                     DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT16Sx8,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ16x8,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* CLE_S.W */
-                     DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT32Sx4,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ32x4,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x05: { /* DPSUB_U.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
 
-               case 0x03: { /* CLE_S.D */
-                     DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT64Sx2,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ64x2,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x01: { /* DPSUB_U.H */
+               DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_Add16,
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU8,
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_Sub16x8,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* DPSUB_U.W */
+               DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-      case 0x05: { /* CLE_U.df */
-            switch (df) {
-               case 0x00: { /* CLE_U.B */
-                     DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT8Ux16,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ8x16,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_Add32,
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU16,
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem16x8,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               case 0x01: { /* CLE_U.H */
-                     DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT16Ux8,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ16x8,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_Sub32x4,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
+            }
 
-               case 0x02: { /* CLE_U.W */
-                     DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT32Ux4,
-                                            mkexpr(t2), mkexpr(t1)),
-                                      binop(Iop_CmpEQ32x4,
-                                            mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* DPSUB_U.D */
+               DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x03: { /* CLE_U.D */
-                     DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_OrV128,
-                                  binop(Iop_CmpGT64Ux2,
-                                        mkexpr(t2), mkexpr(t1)),
-                                  binop(Iop_CmpEQ64x2,
-                                        mkexpr(t1), mkexpr(t2))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_Add64,
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i))),
+                               binop(Iop_MullU32,
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t1),
+                                           mkU8(2 * i + 1)),
+                                     binop(Iop_GetElem32x4,
+                                           mkexpr(t2),
+                                           mkU8(2 * i + 1)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_Sub64x2,
+                             getWReg(wd),
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -16176,706 +10052,723 @@ static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) { /* 3R (0x0F) */
    return 0;
 }
 
-static Int msa_3R_10(UInt cins, UChar wd, UChar ws) { /* 3R (0x10) */
-   IRTemp t1, t2, t3, t4;
-   UShort operation;
-   UChar df, wt;
-
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
-
-   switch (operation) {
-      case 0x00: { /* ADD_A.df */
-            switch (df) {
-               case 0x00: { /* ADD_A.B */
-                     DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
-                     assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+static Int msa_3R_14(UInt cins, UChar wd, UChar ws)   /* 3R (0x14) */
+{
+   IRTemp t1, t2, t3, t4;
+   IRType ty;
+   UShort operation;
+   UChar df, wt;
 
-               case 0x01: { /* ADD_A.H */
-                     DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
-                     assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+   operation = (cins & 0x03800000) >> 23;
+   df = (cins & 0x00600000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
+   ty = mode64 ? Ity_I64 : Ity_I32;
 
-               case 0x02: { /* ADD_A.W */
-                     DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
-                     assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+   switch (operation) {
+      case 0x00: { /* SLD.df */
+         switch (df) {
+            case 0x00: {
+               DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shl32,
+                            binop(Iop_And32,
+                                  mkNarrowTo32(ty,
+                                               getIReg(wt)),
+                                  mkU32(15)),
+                            mkU8(3)));
+               assign(t2,
+                      binop(Iop_ShrV128,
+                            getWReg(ws),
+                            unop(Iop_32to8, mkexpr(t1))));
+               assign(t3,
+                      binop(Iop_ShlV128,
+                            getWReg(wd),
+                            unop(Iop_32to8,
+                                 binop(Iop_Sub32,
+                                       mkU32(128),
+                                       mkexpr(t1)))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t2), mkexpr(t3)));
+               break;
+            }
 
-               case 0x03: { /* ADD_A.D */
-                     DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
-                     assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: {/* SLD.H */
+               DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shl32,
+                            binop(Iop_And32,
+                                  mkNarrowTo32(ty,
+                                               getIReg(wt)),
+                                  mkU32(7)),
+                            mkU8(3)));
+               assign(t2,
+                      binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
+               assign(t3,
+                      binop(Iop_Shr64x2,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkexpr(t2), mkexpr(t2))));
+               assign(t4,
+                      binop(Iop_Shl64x2,
+                            getWReg(wd),
+                            binop(Iop_Sub64x2,
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x40ul),
+                                        mkU64(0x40ul)),
+                                  binop(Iop_64HLtoV128,
+                                        mkexpr(t2),
+                                        mkexpr(t2)))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3),
+                             IRExpr_ITE(
+                                binop(Iop_CmpNE32,
+                                      mkexpr(t1), mkU32(0)),
+                                mkexpr(t4),
+                                binop(Iop_64HLtoV128,
+                                      mkU64(0), mkU64(0)))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x02: {/* SLD.W */
+               DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shl32,
+                            binop(Iop_And32,
+                                  mkNarrowTo32(ty,
+                                               getIReg(wt)),
+                                  mkU32(3)),
+                            mkU8(3)));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            mkexpr(t1), mkexpr(t1)));
+               assign(t3,
+                      binop(Iop_Shr32x4,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkexpr(t2), mkexpr(t2))));
+               assign(t4,
+                      binop(Iop_Shl32x4,
+                            getWReg(wd),
+                            binop(Iop_Sub32x4,
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x2000000020ul),
+                                        mkU64(0x2000000020ul)),
+                                  binop(Iop_64HLtoV128,
+                                        mkexpr(t2),
+                                        mkexpr(t2)))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3),
+                             IRExpr_ITE(
+                                binop(Iop_CmpNE32,
+                                      mkexpr(t1), mkU32(0)),
+                                mkexpr(t4),
+                                binop(Iop_64HLtoV128,
+                                      mkU64(0), mkU64(0)))));
+               break;
             }
 
-            break;
+            case 0x03: { /* SLD.D */
+               DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shl32,
+                            binop(Iop_And32,
+                                  mkNarrowTo32(ty,
+                                               getIReg(wt)),
+                                  mkU32(1)),
+                            mkU8(3)));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            binop(Iop_Or32,
+                                  mkexpr(t1),
+                                  binop(Iop_Shl32,
+                                        mkexpr(t1), mkU8(16))),
+                            binop(Iop_Or32,
+                                  mkexpr(t1),
+                                  binop(Iop_Shl32,
+                                        mkexpr(t1), mkU8(16)))));
+               assign(t3,
+                      binop(Iop_Shr16x8,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkexpr(t2), mkexpr(t2))));
+               assign(t4,
+                      binop(Iop_Shl16x8,
+                            getWReg(wd),
+                            binop(Iop_Sub16x8,
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x10001000100010ul),
+                                        mkU64(0x10001000100010ul)),
+                                  binop(Iop_64HLtoV128,
+                                        mkexpr(t2),
+                                        mkexpr(t2)))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3),
+                             IRExpr_ITE(
+                                binop(Iop_CmpNE32,
+                                      mkexpr(t1), mkU32(0)),
+                                mkexpr(t4),
+                                binop(Iop_64HLtoV128,
+                                      mkU64(0), mkU64(0)))));
+               break;
+            }
          }
 
-      case 0x01: { /* ADDS_A.df */
-            switch (df) {
-               case 0x00: { /* ADDS_A.B */
-                     DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
-                     assign(t3, binop(Iop_SarN8x16,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      mkU8(7)));
-                     assign(t4, binop(Iop_SarN8x16,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t2),
-                                            getWReg(wt)),
-                                      mkU8(7)));
-                     putWReg(wd, binop(Iop_QAdd8Sx16,
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t3)),
-                                                   mkexpr(t1)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t1)),
-                                                   mkexpr(t3))),
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t4)),
-                                                   mkexpr(t2)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t2)),
-                                                   mkexpr(t4)))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* ADDS_A.H */
-                     DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
-                     assign(t3, binop(Iop_SarN16x8,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      mkU8(15)));
-                     assign(t4, binop(Iop_SarN16x8,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t2),
-                                         getWReg(wt)),
-                                   mkU8(15)));
-                     putWReg(wd, binop(Iop_QAdd16Sx8,
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t3)),
-                                                   mkexpr(t1)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t1)),
-                                                   mkexpr(t3))),
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t4)),
-                                                   mkexpr(t2)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t2)),
-                                                   mkexpr(t4)))));
-                     break;
-                  }
+      case 0x01: { /* SPLAT.df */
+         switch (df) {
+               Int i;
 
-               case 0x02: { /* ADDS_A.W */
-                     DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
-                     assign(t3, binop(Iop_SarN32x4,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      mkU8(31)));
-                     assign(t4, binop(Iop_SarN32x4,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t2),
-                                            getWReg(wt)),
-                                      mkU8(31)));
-                     putWReg(wd, binop(Iop_QAdd32Sx4,
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t3)),
-                                                   mkexpr(t1)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t1)),
-                                                   mkexpr(t3))),
-                                       binop(Iop_OrV128,
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t4)),
-                                                   mkexpr(t2)),
-                                             binop(Iop_AndV128,
-                                                   unop(Iop_NotV128,
-                                                        mkexpr(t2)),
-                                                   mkexpr(t4)))));
-                     break;
-                  }
+            case 0x00: { /* SPLAT.B */
+               DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I32);
+               assign(t1, getWReg(ws));
+               assign(t2,
+                      mkNarrowTo32(ty, getIReg(wt)));
+               IRTemp tmp[16];
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I8);
+                  assign(tmp[i],
+                         binop(Iop_GetElem8x16,
+                               mkexpr(t1),
+                               unop(Iop_32to8, mkexpr(t2))));
+               }
 
-               case 0x03: { /* ADDS_A.D */
-                     DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
-                     assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
-                     assign(t3, binop(Iop_SarN64x2,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t1),
-                                            getWReg(ws)),
-                                      mkU8(63)));
-                     assign(t4, binop(Iop_SarN64x2,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t2),
-                                            getWReg(wt)),
-                                      mkU8(63)));
-                     putWReg(wd,
-                             binop(Iop_QAdd64Sx2,
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t3)),
-                                               mkexpr(t1)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t1)),
-                                               mkexpr(t3))),
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t4)),
-                                               mkexpr(t2)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t2)),
-                                               mkexpr(t4)))));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[15]),
+                                               mkexpr(tmp[14])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[13]),
+                                               mkexpr(tmp[12]))),
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[11]),
+                                               mkexpr(tmp[10])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[9]),
+                                               mkexpr(tmp[8])))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* SPLAT.H */
+               DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I32);
+               assign(t1, getWReg(ws));
+               assign(t2,
+                      mkNarrowTo32(ty, getIReg(wt)));
+               IRTemp tmp[8];
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         binop(Iop_GetElem16x8,
+                               mkexpr(t1),
+                               unop(Iop_32to8, mkexpr(t2))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* SPLAT.W */
+               DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I32);
+               assign(t1, getWReg(ws));
+               assign(t2,
+                      mkNarrowTo32(ty, getIReg(wt)));
+               IRTemp tmp[4];
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         binop(Iop_GetElem32x4,
+                               mkexpr(t1),
+                               unop(Iop_32to8, mkexpr(t2))));
+               }
 
-      case 0x02: { /* ADDS_S.df */
-            switch (df) {
-               case 0x00: { /* ADDS_S.B */
-                     DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
 
-               case 0x01: { /* ADDS_S.H */
-                     DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* SPLAT.D */
+               DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I32);
+               assign(t1, getWReg(ws));
+               assign(t2,
+                      mkNarrowTo32(ty, getIReg(wt)));
+               IRTemp tmp[2];
+
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         binop(Iop_GetElem64x2,
+                               mkexpr(t1),
+                               unop(Iop_32to8, mkexpr(t2))));
+               }
 
-               case 0x02: { /* ADDS_S.W */
-                     DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(tmp[1]), mkexpr(tmp[0])));
+               break;
+            }
+         }
 
-               case 0x03: { /* ADDS_S.D */
-                     DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               default:
-                  return -1;
+      case 0x02: { /* PCKEV.df */
+         switch (df) {
+            case 0x00: { /* PCKEV.B */
+               DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackEvenLanes8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
-         }
+            case 0x01: { /* PCKEV.H */
+               DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackEvenLanes16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-      case 0x03: { /* ADDS_U.df */
-            switch (df) {
-               case 0x00: { /* ADDS_U.B */
-                     DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* PCKEV.W */
+               DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackEvenLanes32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x01: { /* ADDS_U.H */
-                     DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* PCKEV.D */
+               DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
+         }
 
-               case 0x02: { /* ADDS_U.W */
-                     DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x03: { /* ADDS_U.D */
-                     DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x03: { /* PCKOD.df */
+         switch (df) {
+            case 0x00: { /* PCKOD.B */
+               DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackOddLanes8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* PCKOD.H */
+               DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackOddLanes16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            case 0x02: { /* PCKOD.W */
+               DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_PackOddLanes32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* PCKOD.D */
+               DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x04: { /* AVE_S.df */
-            switch (df) {
-               case 0x00: { /* AVE_S.B */
-                     DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add8x16,
-                                      binop(Iop_Add8x16,
-                                            binop(Iop_SarN8x16,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_SarN8x16,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN8x16,
-                                            binop(Iop_ShlN8x16,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(7)),
-                                            mkU8(7))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* AVE_S.H */
-                     DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add16x8,
-                                  binop(Iop_Add16x8,
-                                        binop(Iop_SarN16x8,
-                                              mkexpr(t1), mkU8(1)),
-                                        binop(Iop_SarN16x8,
-                                              mkexpr(t2), mkU8(1))),
-                                  binop(Iop_ShrN16x8,
-                                        binop(Iop_ShlN16x8,
-                                              binop(Iop_AndV128,
-                                                    mkexpr(t1),
-                                                    mkexpr(t2)),
-                                              mkU8(15)),
-                                        mkU8(15))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x04: { /* ILVL.df */
+         switch (df) {
+            case 0x00: { /* ILVL.B */
+               DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* AVE_S.W */
-                     DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add32x4,
-                                      binop(Iop_Add32x4,
-                                            binop(Iop_SarN32x4,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_SarN32x4,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN32x4,
-                                            binop(Iop_ShlN32x4,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(31)),
-                                            mkU8(31))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* ILVL.H */
+               DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* AVE_S.D */
-                     DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add64x2,
-                                      binop(Iop_Add64x2,
-                                            binop(Iop_SarN64x2,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_SarN64x2,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN64x2,
-                                            binop(Iop_ShlN64x2,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(63)),
-                                            mkU8(63))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* ILVL.W */
+               DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* ILVL.D */
+               DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* AVE_U.df */
-            switch (df) {
-               case 0x00: { /* AVE_U.B */
-                     DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add16x8,
-                                      binop(Iop_Add8x16,
-                                            binop(Iop_ShrN8x16,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_ShrN8x16,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN8x16,
-                                            binop(Iop_ShlN8x16,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(7)),
-                                            mkU8(7))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-
-               case 0x01: { /* AVE_U.H */
-                     DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add16x8,
-                                      binop(Iop_Add16x8,
-                                            binop(Iop_ShrN16x8,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_ShrN16x8,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN16x8,
-                                            binop(Iop_ShlN16x8,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(15)),
-                                            mkU8(15))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* AVE_U.W */
-                     DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add32x4,
-                                      binop(Iop_Add32x4,
-                                            binop(Iop_ShrN32x4,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_ShrN32x4,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN32x4,
-                                            binop(Iop_ShlN32x4,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(31)),
-                                            mkU8(31))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x05: { /* ILVR.df */
+         switch (df) {
+            case 0x00: { /* ILVL.B */
+               DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* AVE_U.D */
-                     DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add64x2,
-                                      binop(Iop_Add64x2,
-                                            binop(Iop_ShrN64x2,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_ShrN64x2,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN64x2,
-                                            binop(Iop_ShlN64x2,
-                                                  binop(Iop_AndV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(63)),
-                                            mkU8(63))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* ILVL.H */
+               DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x02: { /* ILVL.W */
+               DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            case 0x03: { /* ILVL.D */
+               DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
          }
 
-      case 0x06: { /* AVER_S.df */
-            switch (df) {
-               case 0x00: { /* AVER_S.B */
-                     DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* AVER_S.H */
-                     DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x06: { /* ILVEV.df */
+         switch (df) {
+            case 0x00: { /* ILVEV.B */
+               DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveEvenLanes8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* AVER_S.W */
-                     DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* ILVEV.H */
+               DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveEvenLanes16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* AVER_S.D */
-                     DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add64x2,
-                                      binop(Iop_Add64x2,
-                                            binop(Iop_SarN64x2,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_SarN64x2,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN64x2,
-                                            binop(Iop_ShlN64x2,
-                                                  binop(Iop_OrV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(63)),
-                                            mkU8(63))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* ILVEV.W */
+               DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveEvenLanes32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* ILVEV.D */
+               DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveLO64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x07: { /* AVER_U.df */
-            switch (df) {
-               case 0x00: { /* AVER_U.B */
-                     DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* AVER_U.H */
-                     DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x07: { /* ILVOD.df */
+         switch (df) {
+            case 0x00: { /* ILVOD.B */
+               DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveOddLanes8x16,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* AVER_U.W */
-                     DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* ILVOD.H */
+               DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveOddLanes16x8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* AVER_U.D */
-                     DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_Add64x2,
-                                      binop(Iop_Add64x2,
-                                            binop(Iop_ShrN64x2,
-                                                  mkexpr(t1), mkU8(1)),
-                                            binop(Iop_ShrN64x2,
-                                                  mkexpr(t2), mkU8(1))),
-                                      binop(Iop_ShrN64x2,
-                                            binop(Iop_ShlN64x2,
-                                                  binop(Iop_OrV128,
-                                                        mkexpr(t1),
-                                                        mkexpr(t2)),
-                                                  mkU8(63)),
-                                            mkU8(63))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x02: { /* ILVOD.W */
+               DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveOddLanes32x4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* ILVOD.D */
+               DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_InterleaveHI64x2,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -16883,8 +10776,9 @@ static Int msa_3R_10(UInt cins, UChar wd, UChar ws) { /* 3R (0x10) */
    return 0;
 }
 
-static Int msa_3R_11(UInt cins, UChar wd, UChar ws) { /* 3R (0x11) */
-   IRTemp t1, t2, t3;
+static Int msa_3R_15(UInt cins, UChar wd, UChar ws)   /* 3R (0x15) */
+{
+   IRTemp t1, t2, t3, t4;
    UShort operation;
    UChar df, wt;
 
@@ -16893,671 +10787,831 @@ static Int msa_3R_11(UInt cins, UChar wd, UChar ws) { /* 3R (0x11) */
    wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* SUBS_S.df */
-            switch (df) {
-               case 0x00: { /* SUBS_S.B */
-                     DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x00: { /* VSHF.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1, getWReg(wd));
+         assign(t2, getWReg(ws));
+         assign(t3, getWReg(wt));
 
-               case 0x01: { /* SUBS_S.H */
-                     DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: { /* VSHF.B */
+               DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[16];
+               Int i;
+
+               for (i = 0; i < 16; i++) {
+                  tmp[i] = newTemp(Ity_I8);
+                  assign(tmp[i],
+                         IRExpr_ITE(
+                            binop(Iop_CmpEQ8,
+                                  binop(Iop_And8,
+                                        binop(Iop_GetElem8x16,
+                                              mkexpr(t1),
+                                              mkU8(i)),
+                                        mkU8(0xC0)),
+                                  mkU8(0x0)),
+                            IRExpr_ITE(
+                               binop(Iop_CmpEQ8,
+                                     binop(Iop_And8,
+                                           binop(Iop_GetElem8x16,
+                                                 mkexpr(t1),
+                                                 mkU8(i)),
+                                           mkU8(0x10)),
+                                     mkU8(0x0)),
+                               binop(Iop_GetElem8x16,
+                                     mkexpr(t3),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(i))),
+                               binop(Iop_GetElem8x16,
+                                     mkexpr(t2),
+                                     binop(Iop_GetElem8x16,
+                                           mkexpr(t1),
+                                           mkU8(i)))),
+                            mkU8(0x0)));
+               }
 
-               case 0x02: { /* SUBS_S.W */
-                     DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[15]),
+                                               mkexpr(tmp[14])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[13]),
+                                               mkexpr(tmp[12]))),
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[11]),
+                                               mkexpr(tmp[10])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[9]),
+                                               mkexpr(tmp[8])))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_16HLto32,
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_8HLto16,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0]))))));
+               break;
+            }
 
-               case 0x03: { /* SUBS_S.D */
-                     DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x01: { /* VSHF.H */
+               DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[8];
+               Int i;
+
+               for (i = 0; i < 8; i++) {
+                  tmp[i] = newTemp(Ity_I16);
+                  assign(tmp[i],
+                         IRExpr_ITE(
+                            binop(Iop_CmpEQ16,
+                                  binop(Iop_And16,
+                                        binop(Iop_GetElem16x8,
+                                              mkexpr(t1),
+                                              mkU8(i)),
+                                        mkU16(0xC0)),
+                                  mkU16(0x0)),
+                            IRExpr_ITE(
+                               binop(Iop_CmpEQ16,
+                                     binop(Iop_And16,
+                                           binop(Iop_GetElem16x8,
+                                                 mkexpr(t1),
+                                                 mkU8(i)),
+                                           mkU16(0x08)),
+                                     mkU16(0x0)),
+                               binop(Iop_GetElem16x8,
+                                     mkexpr(t3),
+                                     unop(Iop_16to8,
+                                          binop(Iop_GetElem16x8,
+                                                mkexpr(t1),
+                                                mkU8(i)))),
+                               binop(Iop_GetElem16x8,
+                                     mkexpr(t2),
+                                     unop(Iop_16to8,
+                                          binop(Iop_GetElem16x8,
+                                                mkexpr(t1),
+                                                mkU8(i))))),
+                            mkU16(0x0)));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[7]),
+                                         mkexpr(tmp[6])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[5]),
+                                         mkexpr(tmp[4]))),
+                             binop(Iop_32HLto64,
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_16HLto32,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
-         }
+            case 0x02: { /* VSHF.W */
+               DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[4];
+               Int i;
 
-      case 0x01: { /* SUBS_U.df */
-            switch (df) {
-               case 0x00: { /* SUBS_U.B */
-                     DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         IRExpr_ITE(
+                            binop(Iop_CmpEQ32,
+                                  binop(Iop_And32,
+                                        binop(Iop_GetElem32x4,
+                                              mkexpr(t1),
+                                              mkU8(i)),
+                                        mkU32(0xC0)),
+                                  mkU32(0x0)),
+                            IRExpr_ITE(
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           binop(Iop_GetElem32x4,
+                                                 mkexpr(t1),
+                                                 mkU8(i)),
+                                           mkU32(0x04)),
+                                     mkU32(0x0)),
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t3),
+                                     unop(Iop_32to8,
+                                          binop(Iop_GetElem32x4,
+                                                mkexpr(t1),
+                                                mkU8(i)))),
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t2),
+                                     unop(Iop_32to8,
+                                          binop(Iop_GetElem32x4,
+                                                mkexpr(t1),
+                                                mkU8(i))))),
+                            mkU32(0x0)));
+               }
 
-               case 0x01: { /* SUBS_U.H */
-                     DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[3]),
+                                   mkexpr(tmp[2])),
+                             binop(Iop_32HLto64,
+                                   mkexpr(tmp[1]),
+                                   mkexpr(tmp[0]))));
+               break;
+            }
 
-               case 0x02: { /* SUBS_U.W */
-                     DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* VSHF.D */
+               DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x03: { /* SUBS_U.D */
-                     DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         IRExpr_ITE(
+                            binop(Iop_CmpEQ64,
+                                  binop(Iop_And64,
+                                        binop(Iop_GetElem64x2,
+                                              mkexpr(t1),
+                                              mkU8(i)),
+                                        mkU64(0xC0)),
+                                  mkU64(0x0)),
+                            IRExpr_ITE(
+                               binop(Iop_CmpEQ64,
+                                     binop(Iop_And64,
+                                           binop(Iop_GetElem64x2,
+                                                 mkexpr(t1),
+                                                 mkU8(i)),
+                                           mkU64(0x02)),
+                                     mkU64(0x0)),
+                               binop(Iop_GetElem64x2,
+                                     mkexpr(t3),
+                                     unop(Iop_64to8,
+                                          binop(Iop_GetElem64x2,
+                                                mkexpr(t1),
+                                                mkU8(i)))),
+                               binop(Iop_GetElem64x2,
+                                     mkexpr(t2),
+                                     unop(Iop_64to8,
+                                          binop(Iop_GetElem64x2,
+                                                mkexpr(t1),
+                                                mkU8(i))))),
+                            mkU64(0x0)));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(tmp[1]), mkexpr(tmp[0])));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* SUBSUS_U.df */
-            switch (df) {
-               case 0x00: { /* SUBSUS_U.B */
-                     DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
-                     assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
-                     assign(t3, binop(Iop_OrV128,
-                                      binop(Iop_CmpGT8Ux16,
-                                            getWReg(ws),
-                                            getWReg(wt)),
-                                      binop(Iop_CmpEQ8x16,
-                                            getWReg(ws),
-                                            getWReg(wt))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t3),
-                                               mkexpr(t2)))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* SUBSUS_U.H */
-                     DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
-                     assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
-                     assign(t3,
-                            binop(Iop_OrV128,
-                                  binop(Iop_CmpGT16Ux8,
-                                        getWReg(ws),
-                                        getWReg(wt)),
-                                  binop(Iop_CmpEQ16x8,
+      case 0x01: { /* SRAR.df */
+         switch (df) {
+            case 0x00: { /* SRAR.B */
+               DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Sar8x16,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x808080808080808ull),
+                                  mkU64(0x808080808080808ull)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ8x16,
+                                 binop(Iop_ShlN8x16,
+                                       getWReg(wt),
+                                       mkU8(5)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN8x16,
+                            binop(Iop_AndV128,
+                                  binop(Iop_Shl8x16,
                                         getWReg(ws),
-                                        getWReg(wt))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t3),
-                                               mkexpr(t2)))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(7)));
+               putWReg(wd,
+                       binop(Iop_Add8x16,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               case 0x02: { /* SUBSUS_U.W */
-                     DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
-                     assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
-                     assign(t3,
-                            binop(Iop_OrV128,
-                                  binop(Iop_CmpGT32Ux4,
-                                        getWReg(ws),
-                                        getWReg(wt)),
-                                  binop(Iop_CmpEQ32x4,
+            case 0x01: { /* SRAR.H */
+               DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Sar16x8,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x10001000100010ul),
+                                  mkU64(0x10001000100010ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ16x8,
+                                 binop(Iop_ShlN16x8,
+                                       getWReg(wt),
+                                       mkU8(12)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN16x8,
+                            binop(Iop_AndV128,
+                                  binop(Iop_Shl16x8,
                                         getWReg(ws),
-                                        getWReg(wt))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t3),
-                                               mkexpr(t2)))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(15)));
+               putWReg(wd,
+                       binop(Iop_Add16x8,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               case 0x03: { /* SUBSUS_U.D */
-                     DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
-                     assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
-                     assign(t3,
-                            binop(Iop_OrV128,
-                                  binop(Iop_CmpGT64Ux2,
-                                        getWReg(ws),
-                                        getWReg(wt)),
-                                  binop(Iop_CmpEQ64x2,
+            case 0x02: { /* SRAR.W */
+               DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128); // shifted
+               t2 = newTemp(Ity_V128); // 32 - wt
+               t3 = newTemp(Ity_V128); // rv
+               t4 = newTemp(Ity_V128); // wt % 32 == 0
+               assign(t1,
+                      binop(Iop_Sar32x4,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x2000000020ul),
+                                  mkU64(0x2000000020ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ32x4,
+                                 binop(Iop_ShlN32x4,
+                                       getWReg(wt),
+                                       mkU8(27)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN32x4,
+                            binop(Iop_AndV128,
+                                  binop(Iop_Shl32x4,
                                         getWReg(ws),
-                                        getWReg(wt))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t3),
-                                               mkexpr(t2)))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(31)));
+               putWReg(wd,
+                       binop(Iop_Add32x4,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* SRAR.D */
+               DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Sar64x2,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(64ul), mkU64(64ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ64x2,
+                                 binop(Iop_ShlN64x2,
+                                       getWReg(wt),
+                                       mkU8(58)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN64x2,
+                            binop(Iop_AndV128,
+                                  binop(Iop_Shl64x2,
+                                        getWReg(ws),
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(63)));
+               putWReg(wd,
+                       binop(Iop_Add64x2,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* SUBSUU_S.df */
-            switch (df) {
-               case 0x00: { /* SUBSUU_S.B */
-                     DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_SarN8x16,
-                                  binop (Iop_AndV128,
-                                         binop(Iop_XorV128,
-                                               getWReg(ws),
-                                               getWReg(wt)),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t1),
-                                               getWReg(wt))),
-                                  mkU8(7)));
-                     assign(t3,
-                            binop(Iop_AndV128,
-                                  binop(Iop_SarN8x16,
-                                        getWReg(ws), mkU8(7)),
-                                  mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         unop(Iop_NotV128,
-                                              mkexpr(t2))),
-                                   binop(Iop_XorV128,
-                                         binop(Iop_ShlN8x16,
-                                               mkexpr(t2), mkU8(7)),
-                                         mkexpr(t3))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* SUBSUU_S.H */
-                     DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_SarN16x8,
-                                  binop (Iop_AndV128,
-                                         binop(Iop_XorV128,
-                                               getWReg(ws),
-                                               getWReg(wt)),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t1),
-                                               getWReg(wt))),
-                                  mkU8(15)));
-                     assign(t3,
+      case 0x02: { /* SRLR.df */
+         switch (df) {
+            case 0x00: { /* SRLR.B */
+               DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shr8x16,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub8x16,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x808080808080808ull),
+                                  mkU64(0x808080808080808ull)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ8x16,
+                                 binop(Iop_ShlN8x16,
+                                       getWReg(wt),
+                                       mkU8(5)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN8x16,
                             binop(Iop_AndV128,
-                                  binop(Iop_SarN16x8,
+                                  binop(Iop_Shl8x16,
                                         getWReg(ws),
-                                        mkU8(15)),
-                                  mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         unop(Iop_NotV128,
-                                              mkexpr(t2))),
-                                   binop(Iop_XorV128,
-                                         binop(Iop_ShlN16x8,
-                                               mkexpr(t2), mkU8(15)),
-                                         mkexpr(t3))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(7)));
+               putWReg(wd,
+                       binop(Iop_Add8x16,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               case 0x02: { /* SUBSUU_S.W */
-                     DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_SarN32x4,
-                                  binop (Iop_AndV128,
-                                         binop(Iop_XorV128,
-                                               getWReg(ws),
-                                               getWReg(wt)),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t1),
-                                               getWReg(wt))),
-                                  mkU8(31)));
-                     assign(t3,
+            case 0x01: { /* SRLR.H */
+               DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shr16x8,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub16x8,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x10001000100010ul),
+                                  mkU64(0x10001000100010ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ16x8,
+                                 binop(Iop_ShlN16x8,
+                                       getWReg(wt),
+                                       mkU8(12)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN16x8,
                             binop(Iop_AndV128,
-                                  binop(Iop_SarN32x4,
+                                  binop(Iop_Shl16x8,
                                         getWReg(ws),
-                                        mkU8(31)),
-                                  mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         unop(Iop_NotV128,
-                                              mkexpr(t2))),
-                                   binop(Iop_XorV128,
-                                         binop(Iop_ShlN32x4,
-                                               mkexpr(t2),
-                                               mkU8(31)),
-                                         mkexpr(t3))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(15)));
+               putWReg(wd,
+                       binop(Iop_Add16x8,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               case 0x03: { /* SUBSUU_S.D */
-                     DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_SarN64x2,
-                                  binop (Iop_AndV128,
-                                         binop(Iop_XorV128,
-                                               getWReg(ws),
-                                               getWReg(wt)),
-                                         binop(Iop_XorV128,
-                                               mkexpr(t1),
-                                               getWReg(wt))),
-                                  mkU8(63)));
-                     assign(t3,
+            case 0x02: { /* SRLR.W */
+               DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shr32x4,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x2000000020ul),
+                                  mkU64(0x2000000020ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ32x4,
+                                 binop(Iop_ShlN32x4,
+                                       getWReg(wt),
+                                       mkU8(27)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN32x4,
                             binop(Iop_AndV128,
-                                  binop(Iop_SarN64x2,
+                                  binop(Iop_Shl32x4,
                                         getWReg(ws),
-                                        mkU8(63)),
-                                  mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         unop(Iop_NotV128,
-                                              mkexpr(t2))),
-                                   binop(Iop_XorV128,
-                                         binop(Iop_ShlN64x2,
-                                               mkexpr(t2), mkU8(63)),
-                                         mkexpr(t3))));
-                     break;
-                  }
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(31)));
+               putWReg(wd,
+                       binop(Iop_Add32x4,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* SRLR.D */
+               DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_Shr64x2,
+                            getWReg(ws),
+                            getWReg(wt)));
+               assign(t2,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_64HLtoV128,
+                                  mkU64(64ul), mkU64(64ul)),
+                            getWReg(wt)));
+               assign(t4,
+                      unop(Iop_NotV128,
+                           binop(Iop_CmpEQ64x2,
+                                 binop(Iop_ShlN64x2,
+                                       getWReg(wt),
+                                       mkU8(58)),
+                                 binop(Iop_64HLtoV128,
+                                       mkU64(0), mkU64(0)))));
+               assign(t3,
+                      binop(Iop_ShrN64x2,
+                            binop(Iop_AndV128,
+                                  binop(Iop_Shl64x2,
+                                        getWReg(ws),
+                                        mkexpr(t2)),
+                                  mkexpr(t4)),
+                            mkU8(63)));
+               putWReg(wd,
+                       binop(Iop_Add64x2,
+                             mkexpr(t1), mkexpr(t3)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x04: { /* ASUB_S.df */
-            switch (df) {
-               case 0x00: { /* ASUB_S.B */
-                     DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
-                     assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
-                     assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               binop(Iop_AndV128,
-                                                     unop(Iop_NotV128,
-                                                          mkexpr(t1)),
-                                                     mkexpr(t2)),
-                                               mkexpr(t3)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    binop(Iop_XorV128,
-                                                          mkexpr(t1),
-                                                          mkexpr(t2))),
-                                               unop(Iop_Abs8x16,
-                                                    mkexpr(t3)))),
-                                   binop(Iop_AndV128,
-                                         binop(Iop_AndV128,
-                                               mkexpr(t1),
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Sub8x16,
-                                               getWReg(wt),
-                                               getWReg(ws)))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* ASUB_S.H */
-                     DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
-                     assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
-                     assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               binop(Iop_AndV128,
-                                                     unop(Iop_NotV128,
-                                                          mkexpr(t1)),
-                                                     mkexpr(t2)),
-                                               mkexpr(t3)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    binop(Iop_XorV128,
-                                                          mkexpr(t1),
-                                                          mkexpr(t2))),
-                                               unop(Iop_Abs16x8,
-                                                    mkexpr(t3)))),
-                                   binop(Iop_AndV128,
-                                         binop(Iop_AndV128,
-                                               mkexpr(t1),
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Sub16x8,
-                                               getWReg(wt),
-                                               getWReg(ws)))));
-                     break;
-                  }
+      case 0x04: { /* HADD_S.df */
+         switch (df) {
+            case 0x01: { /* HADD_S.H */
+               DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add16x8,
+                            binop(Iop_SarN16x8,
+                                  mkexpr(t1), mkU8(8)),
+                            binop(Iop_SarN16x8,
+                                  binop(Iop_ShlN16x8,
+                                        mkexpr(t2), mkU8(8)),
+                                  mkU8(8))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* ASUB_S.W */
-                     DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
-                     assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
-                     assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               binop(Iop_AndV128,
-                                                     unop(Iop_NotV128,
-                                                          mkexpr(t1)),
-                                                     mkexpr(t2)),
-                                               mkexpr(t3)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    binop(Iop_XorV128,
-                                                          mkexpr(t1),
-                                                          mkexpr(t2))),
-                                               unop(Iop_Abs32x4,
-                                                    mkexpr(t3)))),
-                                   binop(Iop_AndV128,
-                                         binop(Iop_AndV128,
-                                               mkexpr(t1),
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Sub32x4,
-                                               getWReg(wt),
-                                               getWReg(ws)))));
-                     break;
-                  }
+            case 0x02: { /* HADD_S.W */
+               DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add32x4,
+                            binop(Iop_SarN32x4,
+                                  mkexpr(t1), mkU8(16)),
+                            binop(Iop_SarN32x4,
+                                  binop(Iop_ShlN32x4,
+                                        mkexpr(t2), mkU8(16)),
+                                  mkU8(16))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* ASUB_S.D */
-                     DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
-                     assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
-                     assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_OrV128,
-                                         binop(Iop_AndV128,
-                                               binop(Iop_AndV128,
-                                                     unop(Iop_NotV128,
-                                                          mkexpr(t1)),
-                                                     mkexpr(t2)),
-                                               mkexpr(t3)),
-                                         binop(Iop_AndV128,
-                                               unop(Iop_NotV128,
-                                                    binop(Iop_XorV128,
-                                                          mkexpr(t1),
-                                                          mkexpr(t2))),
-                                               unop(Iop_Abs64x2,
-                                                    mkexpr(t3)))),
-                                   binop(Iop_AndV128,
-                                         binop(Iop_AndV128,
-                                               mkexpr(t1),
-                                               unop(Iop_NotV128,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Sub64x2,
-                                               getWReg(wt),
-                                               getWReg(ws)))));
-                     break;
-                  }
+            case 0x03: { /* HADD_S.D */
+               DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add64x2,
+                            binop(Iop_SarN64x2,
+                                  mkexpr(t1), mkU8(32)),
+                            binop(Iop_SarN64x2,
+                                  binop(Iop_ShlN64x2,
+                                        mkexpr(t2), mkU8(32)),
+                                  mkU8(32))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x05: { /* HADD_U.df */
+         switch (df) {
+            case 0x01: { /* HADD_U.H */
+               DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add16x8,
+                            binop(Iop_ShrN16x8,
+                                  mkexpr(t1), mkU8(8)),
+                            binop(Iop_ShrN16x8,
+                                  binop(Iop_ShlN16x8,
+                                        mkexpr(t2), mkU8(8)),
+                                  mkU8(8))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            case 0x02: { /* HADD_U.W */
+               DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add32x4,
+                            binop(Iop_ShrN32x4,
+                                  mkexpr(t1), mkU8(16)),
+                            binop(Iop_ShrN32x4,
+                                  binop(Iop_ShlN32x4,
+                                        mkexpr(t2), mkU8(16)),
+                                  mkU8(16))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* HADD_U.D */
+               DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Add64x2,
+                            binop(Iop_ShrN64x2,
+                                  mkexpr(t1), mkU8(32)),
+                            binop(Iop_ShrN64x2,
+                                  binop(Iop_ShlN64x2,
+                                        mkexpr(t2), mkU8(32)),
+                                  mkU8(32))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x05: { /* ASUB_U.df */
-            switch (df) {
-               case 0x00: { /* ASUB_U.B */
-                     DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_SarN8x16,
-                                  binop(Iop_XorV128,
-                                        mkexpr(t1), mkexpr(t2)),
-                                  mkU8(7)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         unop(Iop_NotV128, mkexpr(t3)),
-                                         unop(Iop_Abs8x16,
-                                              binop(Iop_Sub8x16,
-                                                    mkexpr(t1),
-                                                    mkexpr(t2)))),
-                                   binop(Iop_AndV128, mkexpr(t3),
-                                         binop(Iop_Sub8x16,
-                                               binop(Iop_Max8Ux16,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2)),
-                                               binop(Iop_Min8Ux16,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2))))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* ASUB_U.H */
-                     DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
+      case 0x06: { /* HSUB_S.df */
+         switch (df) {
+            case 0x01: { /* HSUB_S.H */
+               DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub16x8,
                             binop(Iop_SarN16x8,
-                                  binop(Iop_XorV128,
-                                        mkexpr(t1), mkexpr(t2)),
-                                  mkU8(15)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         unop(Iop_NotV128,
-                                              mkexpr(t3)),
-                                         unop(Iop_Abs16x8,
-                                              binop(Iop_Sub16x8,
-                                                    mkexpr(t1),
-                                                    mkexpr(t2)))),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3),
-                                         binop(Iop_Sub16x8,
-                                               binop(Iop_Max16Ux8,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2)),
-                                               binop(Iop_Min16Ux8,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2))))));
-                     break;
-                  }
+                                  mkexpr(t1), mkU8(8)),
+                            binop(Iop_SarN16x8,
+                                  binop(Iop_ShlN16x8,
+                                        mkexpr(t2), mkU8(8)),
+                                  mkU8(8))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* ASUB_U.W */
-                     DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
+            case 0x02: { /* HSUB_S.W */
+               DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub32x4,
                             binop(Iop_SarN32x4,
-                                  binop(Iop_XorV128,
-                                        mkexpr(t1), mkexpr(t2)),
-                                  mkU8(31)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         unop(Iop_NotV128, mkexpr(t3)),
-                                         unop(Iop_Abs32x4,
-                                              binop(Iop_Sub32x4,
-                                                    mkexpr(t1),
-                                                    mkexpr(t2)))),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3),
-                                         binop(Iop_Sub32x4,
-                                               binop(Iop_Max32Ux4,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2)),
-                                               binop(Iop_Min32Ux4,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2))))));
-                     break;
-                  }
+                                  mkexpr(t1), mkU8(16)),
+                            binop(Iop_SarN32x4,
+                                  binop(Iop_ShlN32x4,
+                                        mkexpr(t2), mkU8(16)),
+                                  mkU8(16))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            case 0x03: { /* HSUB_S.D */
+               DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_SarN64x2,
+                                  mkexpr(t1), mkU8(32)),
+                            binop(Iop_SarN64x2,
+                                  binop(Iop_ShlN64x2,
+                                        mkexpr(t2), mkU8(32)),
+                                  mkU8(32))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
+
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x07: { /* HSUB_U.df */
+         switch (df) {
+            case 0x01: { /* HSUB_U.H */
+               DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub16x8,
+                            binop(Iop_ShrN16x8,
+                                  mkexpr(t1), mkU8(8)),
+                            binop(Iop_ShrN16x8,
+                                  binop(Iop_ShlN16x8,
+                                        mkexpr(t2), mkU8(8)),
+                                  mkU8(8))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x03: { /* ASUB_U.D */
-                     DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_XorV128,
-                                        mkexpr(t1), mkexpr(t2)),
-                                  mkU8(63)));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         unop(Iop_NotV128, mkexpr(t3)),
-                                         unop(Iop_Abs64x2,
-                                              binop(Iop_Sub64x2,
-                                                    mkexpr(t1),
-                                                    mkexpr(t2)))),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t3),
-                                         binop(Iop_Sub64x2,
-                                               binop(Iop_Max64Ux2,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2)),
-                                               binop(Iop_Min64Ux2,
-                                                     mkexpr(t1),
-                                                     mkexpr(t2))))));
-                     break;
-                  }
+            case 0x02: { /* HSUB_U.W */
+               DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_ShrN32x4,
+                                  mkexpr(t1), mkU8(16)),
+                            binop(Iop_ShrN32x4,
+                                  binop(Iop_ShlN32x4,
+                                        mkexpr(t2), mkU8(16)),
+                                  mkU8(16))));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x03: { /* HSUB_U.D */
+               DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_ShrN64x2,
+                                  mkexpr(t1), mkU8(32)),
+                            binop(Iop_ShrN64x2,
+                                  binop(Iop_ShlN64x2,
+                                        mkexpr(t2), mkU8(32)),
+                                  mkU8(32))));
+               putWReg(wd, mkexpr(t3));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -17565,1653 +11619,2129 @@ static Int msa_3R_11(UInt cins, UChar wd, UChar ws) { /* 3R (0x11) */
    return 0;
 }
 
-static Int msa_3R_12(UInt cins, UChar wd, UChar ws) { /* 3R (0x12) */
-   IRTemp t1, t2, t3, t4, t5, t6;
+static Int msa_3R_1A(UInt cins, UChar wd, UChar ws)   /* 3R (0x1A) */
+{
    UShort operation;
    UChar df, wt;
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
+   operation = (cins & 0x03C00000) >> 22;
+   df = (cins & 0x00200000) >> 21;
    wt = (cins & 0x001F0000) >> 16;
 
    switch (operation) {
-      case 0x00: { /* MULV.df */
-            switch (df) {
-               case 0x00: { /* MULV.B */
-                     DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
-                     break;
-                  }
+      case 0x00: { /* FCAF.df */
+         switch (df) {
+            case 0x00: { /* FCAF.W */
+               DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCAFW, 2);
+               putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
+               break;
+            }
 
-               case 0x01: { /* MULV.H */
-                     DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
-                     break;
-                  }
+            case 0x01: { /* FCAF.D */
+               DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCAFD, 2);
+               putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
+               break;
+            }
 
-               case 0x02: { /* MULV.W */
-                     DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x03: { /* MULV.D */
-                     DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_Mul64,
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t2))),
-                                   binop(Iop_Mul64,
-                                         unop(Iop_V128to64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128to64,
-                                              mkexpr(t2)))));
-                     break;
-                  }
+         break;
+      }
 
-               default:
-                  return -1;
+      case 0x01: { /* FCUN.df */
+         switch (df) {
+            case 0x00: { /* FCUN.W */
+               DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUNW, 2);
+               putWReg(wd, binop(Iop_CmpUN32Fx4,
+                                 getWReg(ws),
+                                 getWReg(wt)));
+               break;
             }
 
-            break;
+            case 0x01: { /* FCUN.D */
+               DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUND, 2);
+               putWReg(wd, binop(Iop_CmpUN64Fx2,
+                                 getWReg(ws),
+                                 getWReg(wt)));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x01: { /* MADDV.df */
-            switch (df) {
-               case 0x00: { /* MADDV.B */
-                     DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Add8x16,
-                                   getWReg(wd),
-                                   binop(Iop_Mul8x16,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MADDV.H */
-                     DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Add16x8,
-                                   getWReg(wd),
-                                   binop(Iop_Mul16x8,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x02: { /* FCEQ.df */
+         switch (df) {
+            case 0x00: { /* FCEQ.W */
+               DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCEQW, 2);
+               putWReg(wd, binop(Iop_CmpEQ32Fx4,
+                                 getWReg(ws),
+                                 getWReg(wt)));
+               break;
+            }
 
-               case 0x02: { /* MADDV.W */
-                     DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Add32x4,
-                                   getWReg(wd),
-                                   binop(Iop_Mul32x4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+            case 0x01: { /* FCEQ.D */
+               DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCEQD, 2);
+               putWReg(wd, binop(Iop_CmpEQ64Fx2,
+                                 getWReg(ws),
+                                 getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* MADDV.D */
-                     DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     putWReg(wd,
-                             binop(Iop_Add64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_Mul64,
-                                               unop(Iop_V128HIto64,
-                                                    mkexpr(t1)),
-                                               unop(Iop_V128HIto64,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Mul64,
-                                               unop(Iop_V128to64,
-                                                    mkexpr(t1)),
-                                               unop(Iop_V128to64,
-                                                    mkexpr(t2))))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               default:
-                  return -1;
+         break;
+      }
+
+      case 0x03: { /* FCUEQ.df */
+         switch (df) {
+            case 0x00: { /* FCUEQ.W */
+               DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUEQW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpEQ32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
             }
 
-            break;
+            case 0x01: { /* FCUEQ.D */
+               DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUEQD, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpEQ64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x02: { /* MSUBV.df */
-            switch (df) {
-               case 0x00: { /* MSUBV.B */
-                     DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Sub8x16,
-                                   getWReg(wd),
-                                   binop(Iop_Mul8x16,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MSUBV.H */
-                     DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Sub16x8,
-                                   getWReg(wd),
-                                   binop(Iop_Mul16x8,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x04: { /* FCLT.df */
+         switch (df) {
+            case 0x00: { /* FCLT.W */
+               DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCLTW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLT32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x02: { /* MSUBV.W */
-                     DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_Sub32x4,
-                                   getWReg(wd),
-                                   binop(Iop_Mul32x4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+            case 0x01: { /* FCLT.D */
+               DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCLTD, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLT64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* MSUBV.D */
-                     DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     putWReg(wd,
-                             binop(Iop_Sub64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_Mul64,
-                                               unop(Iop_V128HIto64,
-                                                    mkexpr(t1)),
-                                               unop(Iop_V128HIto64,
-                                                    mkexpr(t2))),
-                                         binop(Iop_Mul64,
-                                               unop(Iop_V128to64,
-                                                    mkexpr(t1)),
-                                               unop(Iop_V128to64,
-                                                    mkexpr(t2))))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               default:
-                  return -1;
+         break;
+      }
+
+      case 0x05: { /* FCULT.df */
+         switch (df) {
+            case 0x00: { /* FCULT.W */
+               DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCULTW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLT32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            case 0x01: { /* FCULT.D */
+               DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCULTD, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLT64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x06: { /* FCLE.df */
+         switch (df) {
+            case 0x00: { /* FCLE.W */
+               DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCLEW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLE32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
+
+            case 0x01: { /* FCLE.D */
+               DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCLED, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLE64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
+
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x07: { /* FCULE.df */
+         switch (df) {
+            case 0x00: { /* FCULE.W */
+               DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCULEW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLE32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            case 0x01: { /* FCULE.D */
+               DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCULED, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLE64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x08: { /* FSAF.df */
+         switch (df) {
+            case 0x00: { /* FSAF.W */
+               DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSAFW, 2);
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkU64(0ul), mkU64(0ul)));
+               break;
+            }
+
+            case 0x01: { /* FSAF.D */
+               DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSAFD, 2);
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkU64(0ul), mkU64(0ul)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x04: { /* DIV_S.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
-
-            switch (df) {
-               case 0x00: { /* DIV_S.B */
-                     DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[16];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                                 binop(Iop_And32,
-                                       mkU32(0xFF),
-                                       binop(Iop_DivS32,
-                                             unop(Iop_8Sto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t1),
-                                                        mkU8(i))),
-                                             unop(Iop_8Sto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t2),
-                                                        mkU8(i))))),
-                                 mkU8((i & 3) << 3)));
-                     }
+      case 0x09: { /* FSUN.df */
+         switch (df) {
+            case 0x00: { /* FSUN.W */
+               DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUNW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpUN32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                          binop(Iop_64HLtoV128,
-                             binop(Iop_32HLto64,
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[15]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[14]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[13]),
-                                                     mkexpr(tmp[12])))),
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[11]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[10]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[9]),
-                                                     mkexpr(tmp[8]))))),
-                             binop(Iop_32HLto64,
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[7]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[6]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[5]),
-                                                     mkexpr(tmp[4])))),
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[3]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[2]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[1]),
-                                                     mkexpr(tmp[0]))))))
-                     );
-                     break;
-                  }
+            case 0x01: { /* FSUN.D */
+               DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUND, 2);
+               putWReg(wd,
+                       binop(Iop_CmpUN64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x01: { /* DIV_S.H */
-                     DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                            binop(Iop_Shl32,
-                                  binop(Iop_And32,
-                                     mkU32(0xFFFF),
-                                     binop(Iop_DivS32,
-                                           unop(Iop_16Sto32,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t1),
-                                                      mkU8(i))),
-                                           unop(Iop_16Sto32,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t2),
-                                                      mkU8(i))))),
-                                  mkU8((i & 1) << 4)));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+      case 0x0A: { /* FSEQ.df */
+         switch (df) {
+            case 0x00: { /* FSEQ.W */
+               DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSEQW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpEQ32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x02: { /* DIV_S.W */
-                     DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+            case 0x01: { /* FSEQ.D */
+               DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSEQD, 2);
+               putWReg(wd,
+                       binop(Iop_CmpEQ64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_DivS32,
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t1), mkU8(i)),
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t2), mkU8(i))));
-                     }
+            default:
+               return -1;
+         }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128, \
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x03: { /* DIV_S.D */
-                     DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_DivS64,
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t2))),
-                                   binop(Iop_DivS64,
-                                         unop(Iop_V128to64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128to64,
-                                              mkexpr(t2)))));
-                     break;
-                  }
+      case 0x0B: { /* FSUEQ.df */
+         switch (df) {
+            case 0x00: { /* FSUEQ.W */
+               DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUEQW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpEQ32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FSUEQ.D */
+               DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUEQD, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpEQ64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* DIV_U.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* DIV_U.B */
-                     DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[16];
-                     Int i;
+      case 0x0C: { /* FSLT.df */
+         switch (df) {
+            case 0x00: { /* FSLT.W */
+               DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSLTW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLT32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                            binop(Iop_Shl32,
-                               binop(Iop_And32,
-                                     mkU32(0xFF),
-                                     binop(Iop_DivU32,
-                                           unop(Iop_8Uto32,
-                                                binop(Iop_GetElem8x16,
-                                                      mkexpr(t1),
-                                                      mkU8(i))),
-                                           unop(Iop_8Uto32,
-                                                binop(Iop_GetElem8x16,
-                                                      mkexpr(t2),
-                                                      mkU8(i))))),
-                               mkU8((i & 3) << 3)));
-                     }
+            case 0x01: { /* FSLT.D */
+               DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSLTD, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLT64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                        binop(Iop_64HLtoV128,
-                             binop(Iop_32HLto64,
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[15]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[14]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[13]),
-                                                     mkexpr(tmp[12])))),
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[11]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[10]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[9]),
-                                                     mkexpr(tmp[8]))))),
-                             binop(Iop_32HLto64,
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[7]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[6]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[5]),
-                                                     mkexpr(tmp[4])))),
-                                   binop(Iop_Or32,
-                                         mkexpr(tmp[3]),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[2]),
-                                               binop(Iop_Or32,
-                                                     mkexpr(tmp[1]),
-                                                     mkexpr(tmp[0]))))))
-                     );
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x01: { /* DIV_U.H */
-                     DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                               binop(Iop_And32,
-                                     mkU32(0xFFFF),
-                                     binop(Iop_DivU32,
-                                           unop(Iop_16Uto32,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t1),
-                                                      mkU8(i))),
-                                           unop(Iop_16Uto32,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t2),
-                                                      mkU8(i))))),
-                               mkU8((i & 1) << 4)));
-                     }
+      case 0x0D: { /* FSULT.df */
+         switch (df) {
+            case 0x00: { /* FSULT.W */
+               DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSULTW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLT32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            case 0x01: { /* FSULT.D */
+               DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSULTD, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLT64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
+         }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x02: { /* DIV_U.W */
-                     DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+      case 0x0E: { /* FSLE.df */
+         switch (df) {
+            case 0x00: { /* FSLE.W */
+               DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSLEW, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLE32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_DivU32,
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t1), mkU8(i)),
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t2), mkU8(i))));
-                     }
+            case 0x01: { /* FSLE.D */
+               DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSLED, 2);
+               putWReg(wd,
+                       binop(Iop_CmpLE64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x03: { /* DIV_U.D */
-                     DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_DivU64,
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128HIto64,
-                                              mkexpr(t2))),
-                                   binop(Iop_DivU64,
-                                         unop(Iop_V128to64,
-                                              mkexpr(t1)),
-                                         unop(Iop_V128to64,
-                                              mkexpr(t2)))));
-                     break;
-                  }
+         break;
+      }
 
-               default:
-                  return -1;
+      case 0x0F: { /* FSULE.df */
+         switch (df) {
+            case 0x00: { /* FSULE.W */
+               DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSULEW, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLE32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
             }
 
-            break;
+            case 0x01: { /* FSULE.D */
+               DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSULED, 2);
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_CmpLE64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt)),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x06: { /* MOD_S.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MOD_S.B */
-                     DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[16];
-                     Int i;
+      default:
+         return -1;
+   }
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                              binop(Iop_And32,
-                                  mkU32(0xFF),
-                                  unop(Iop_64HIto32,
-                                       binop(Iop_DivModS32to32,
-                                             unop(Iop_8Sto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t1),
-                                                        mkU8(i))),
-                                             unop(Iop_8Sto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t2),
-                                                        mkU8(i)))))),
-                              mkU8((i & 3) << 3)));
-                     }
+   return 0;
+}
 
-                     putWReg(wd,
-                        binop(Iop_64HLtoV128,
-                           binop(Iop_32HLto64,
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[15]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[14]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[13]),
-                                                  mkexpr(tmp[12])))),
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[11]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[10]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[9]),
-                                                  mkexpr(tmp[8]))))),
-                           binop(Iop_32HLto64,
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[7]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[6]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4])))),
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[3]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[2]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0])))))));
-                     break;
-                  }
+static Int msa_3R_1B(UInt cins, UChar wd, UChar ws)   /* 3R (0x1B) */
+{
+   IRTemp t1, t2, t3, t4;
+   UShort operation;
+   UChar df, wt;
 
-               case 0x01: { /* MOD_S.H */
-                     DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+   operation = (cins & 0x03C00000) >> 22;
+   df = (cins & 0x00200000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                              binop(Iop_And32,
-                                  mkU32(0xFFFF),
-                                  unop(Iop_64HIto32,
-                                       binop(Iop_DivModS32to32,
-                                             unop(Iop_16Sto32,
-                                                  binop(Iop_GetElem16x8,
-                                                        mkexpr(t1),
-                                                        mkU8(i))),
-                                             unop(Iop_16Sto32,
-                                                  binop(Iop_GetElem16x8,
-                                                        mkexpr(t2),
-                                                        mkU8(i)))))),
-                              mkU8((i & 1) << 4)));
-                     }
+   switch (operation) {
+      case 0x00: { /* FADD.df */
+         switch (df) {
+            case 0x00: { /* FADD.W */
+               DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FADDW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Add32Fx4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            case 0x01: { /* FADD.D */
+               DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FADDD, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Add64Fx2, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x02: { /* MOD_S.W */
-                     DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               unop(Iop_64HIto32,
-                                    binop(Iop_DivModS32to32,
-                                            binop(Iop_GetElem32x4,
-                                                  mkexpr(t1),
-                                                  mkU8(i)),
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t2),
-                                                mkU8(i)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+      case 0x01: { /* FSUB.df */
+         switch (df) {
+            case 0x00: { /* FSUB.W */
+               DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUBW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Sub32Fx4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* MOD_S.D */
-                     DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
-                     assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
-                     assign(t5, unop(Iop_V128to64, mkexpr(t1)));
-                     assign(t6, unop(Iop_V128to64, mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_Sub64,
-                                         mkexpr(t3),
-                                         binop(Iop_Mul64,
-                                               mkexpr(t4),
-                                               binop(Iop_DivS64,
-                                                     mkexpr(t3),
-                                                     mkexpr(t4)))),
-                                   binop(Iop_Sub64,
-                                         mkexpr(t5),
-                                         binop(Iop_Mul64,
-                                               mkexpr(t6),
-                                               binop(Iop_DivS64,
-                                                     mkexpr(t5),
-                                                     mkexpr(t6))))));
-                     break;
-                  }
+            case 0x01: { /* FSUB.D */
+               DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUBD, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Sub64Fx2, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               default:
-                  return -1;
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x02: { /* FMUL.df */
+         switch (df) {
+            case 0x00: { /* FMUL.W */
+               DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMULW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Mul32Fx4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
             }
 
-            break;
+            case 0x01: { /* FMUL.D */
+               DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMULW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Mul64Fx2, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x07: { /* MOD_U.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* MOD_U.B */
-                     DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[16];
-                     Int i;
+      case 0x03: { /* FDIV.df */
+         switch (df) {
+            case 0x00: { /* FDIV.W */
+               DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FDIVW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Div32Fx4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                              binop(Iop_And32,
-                                  mkU32(0xFF),
-                                  unop(Iop_64HIto32,
-                                       binop(Iop_DivModU32to32,
-                                             unop(Iop_8Uto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t1),
-                                                        mkU8(i))),
-                                             unop(Iop_8Uto32,
-                                                  binop(Iop_GetElem8x16,
-                                                        mkexpr(t2),
-                                                        mkU8(i)))))),
-                              mkU8((i & 3) << 3)));
-                     }
+            case 0x01: { /* FDIV.D */
+               DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FDIVD, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Div64Fx2, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                        binop(Iop_64HLtoV128,
-                          binop(Iop_32HLto64,
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[15]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[14]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[13]),
-                                                  mkexpr(tmp[12])))),
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[11]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[10]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[9]),
-                                                  mkexpr(tmp[8]))))),
-                          binop(Iop_32HLto64,
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[7]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[6]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4])))),
-                                binop(Iop_Or32,
-                                      mkexpr(tmp[3]),
-                                      binop(Iop_Or32,
-                                            mkexpr(tmp[2]),
-                                            binop(Iop_Or32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0])))))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x01: { /* MOD_U.H */
-                     DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                           binop(Iop_Shl32,
-                              binop(Iop_And32,
-                                  mkU32(0xFFFF),
-                                  unop(Iop_64HIto32,
-                                       binop(Iop_DivModU32to32,
-                                             unop(Iop_16Uto32,
-                                                  binop(Iop_GetElem16x8,
-                                                        mkexpr(t1),
-                                                        mkU8(i))),
-                                             unop(Iop_16Uto32,
-                                                  binop(Iop_GetElem16x8,
-                                                        mkexpr(t2),
-                                                        mkU8(i)))))),
-                              mkU8((i & 1) << 4)));
-                     }
+      case 0x04: { /* FMADD.df */
+         switch (df) {
+            case 0x00: { /* FMADD.W */
+               DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMADDW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_F32);
+                  assign(tmp[i],
+                         qop(Iop_MAddF32, rm,
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(ws),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(wt),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(wd),
+                                        mkU8(i)))));
+               }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_Or32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[3])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[2]))),
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[1])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[0])))));
+               break;
+            }
+
+            case 0x01: { /* FMADD.D */
+               DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMADDW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               IRTemp tmp[2];
+               Int i;
+
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_F64);
+                  assign(tmp[i],
+                         qop(Iop_MAddF64, rm,
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(ws),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(wt),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(wd),
+                                        mkU8(i)))));
+               }
 
-               case 0x02: { /* MOD_U.W */
-                     DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[1])),
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[0]))));
+               break;
+            }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               unop(Iop_64HIto32,
-                                    binop(Iop_DivModU32to32,
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t1),
-                                                mkU8(i)),
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t2),
-                                                mkU8(i)))));
-                     }
+            default:
+               return -1;
+         }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x03: { /* MOD_U.D */
-                     DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t3 = newTemp(Ity_I64);
-                     t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-                     assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
-                     assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
-                     assign(t5, unop(Iop_V128to64, mkexpr(t1)));
-                     assign(t6, unop(Iop_V128to64, mkexpr(t2)));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_Sub64,
-                                         mkexpr(t3),
-                                         binop(Iop_Mul64,
-                                               mkexpr(t4),
-                                               binop(Iop_DivU64,
-                                                     mkexpr(t3),
-                                                     mkexpr(t4)))),
-                                   binop(Iop_Sub64,
-                                         mkexpr(t5),
-                                         binop(Iop_Mul64,
-                                               mkexpr(t6),
-                                               binop(Iop_DivU64,
-                                                     mkexpr(t5),
-                                                     mkexpr(t6))))));
-                     break;
-                  }
+      case 0x05: { /* FMSUB.df */
+         switch (df) {
+            case 0x00: { /* FMSUB.W */
+               DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMADDW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_F32);
+                  assign(tmp[i],
+                         qop(Iop_MSubF32, rm,
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(ws),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(wt),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI32asF32,
+                                  binop(Iop_GetElem32x4,
+                                        getWReg(wd),
+                                        mkU8(i)))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[3])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[2]))),
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[1])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[0])))));
+               break;
             }
 
-            break;
+            case 0x01: { /* FMSUB.D */
+               DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMADDD, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               IRTemp tmp[2];
+               Int i;
+
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_F64);
+                  assign(tmp[i],
+                         qop(Iop_MSubF64, rm,
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(ws),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(wt),
+                                        mkU8(i))),
+                             unop(Iop_ReinterpI64asF64,
+                                  binop(Iop_GetElem64x2,
+                                        getWReg(wd),
+                                        mkU8(i)))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[1])),
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[0]))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
 
-   return 0;
-}
+      case 0x07: { /* FEXP2.df */
+         switch (df) {
+            case 0x00: { /* FEXP2.W */
+               DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FEXP2W, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Scale2_32Fx4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-static Int msa_3R_13(UInt cins, UChar wd, UChar ws) { /* 3R (0x13) */
-   IRTemp t1, t2;
-   UShort operation;
-   UChar df, wt;
+            case 0x01: { /* FEXP2.D */
+               DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FEXP2D, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_Scale2_64Fx2, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+            default:
+               return -1;
+         }
 
-   switch (operation) {
-      case 0x00: { /* DOTP_S.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DOTP_S.H */
-                     DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      case 0x08: { /* FEXDO.df */
+         switch (df) {
+            case 0x00: { /* FEXDO.H */
+               DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FEXDOH, 2);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               assign(t1,
+                      unop(Iop_F32toF16x4_DEP,
+                           getWReg(ws)));
+               assign(t2,
+                      unop(Iop_F32toF16x4_DEP,
+                           getWReg(wt)));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t1), mkexpr(t2)));
+               break;
+            }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            case 0x01: { /* FEXDO.W */
+               DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FEXDOW, 2);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               t4 = newTemp(Ity_I32);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      unop(Iop_ReinterpF32asI32,
+                           binop(Iop_F64toF32, rm,
+                                 unop(Iop_ReinterpI64asF64,
+                                      unop(Iop_V128to64,
+                                           getWReg(ws))))));
+               assign(t2,
+                      unop(Iop_ReinterpF32asI32,
+                           binop(Iop_F64toF32, rm,
+                                 unop(Iop_ReinterpI64asF64,
+                                      unop(Iop_V128HIto64,
+                                           getWReg(ws))))));
+               assign(t3,
+                      unop(Iop_ReinterpF32asI32,
+                           binop(Iop_F64toF32, rm,
+                                 unop(Iop_ReinterpI64asF64,
+                                      unop(Iop_V128to64,
+                                           getWReg(wt))))));
+               assign(t4,
+                      unop(Iop_ReinterpF32asI32,
+                           binop(Iop_F64toF32, rm,
+                                 unop(Iop_ReinterpI64asF64,
+                                      unop(Iop_V128HIto64,
+                                           getWReg(wt))))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   mkexpr(t2), mkexpr(t1)),
+                             binop(Iop_32HLto64,
+                                   mkexpr(t4), mkexpr(t3))));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x02: { /* DOTP_S.W */
-                     DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+      case 0x0A: { /* FTQ.df */
+         switch (df) {
+            case 0x00: { /* FTQ.H */
+               DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FTQH, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_F32x4_2toQ16x8, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+            case 0x01: { /* FTQ.W */
+               DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FTQW, 2);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               putWReg(wd,
+                       triop(Iop_F64x2_2toQ32x4, rm,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* DOTP_S.D */
-                     DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(tmp[1]), mkexpr(tmp[0])));
-                     break;
-                  }
+      case 0x0C: { /* FMIN.df */
+         switch (df) {
+            case 0x00: { /* FMIN.W */
+               DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMINW, 2);
+               putWReg(wd,
+                       binop(Iop_Min32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FMIN.D */
+               DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMINW, 2);
+               putWReg(wd,
+                       binop(Iop_Min64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x01: { /* DOTP_U.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DOTP_U.H */
-                     DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      case 0x0D: { /* FMIN_A.df */
+         switch (df) {
+            case 0x00: { /* FMIN_A.W */
+               DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMINAW, 2);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_AndV128,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFF7FFFFFFF),
+                                  mkU64(0x7FFFFFFF7FFFFFFF))));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            getWReg(wt),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFF7FFFFFFF),
+                                  mkU64(0x7FFFFFFF7FFFFFFF))));
+               assign(t3,
+                      binop(Iop_Min32Fx4,
+                            mkexpr(t2), mkexpr(t1)));
+               assign(t4,
+                      binop(Iop_AndV128,
+                            binop(Iop_AndV128,
+                                  unop(Iop_NotV128,
+                                       binop(Iop_CmpUN32Fx4,
+                                             mkexpr(t3),
+                                             mkexpr(t3))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              binop(Iop_CmpEQ32Fx4,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2)),
+                                              binop(Iop_OrV128,
+                                                    getWReg(ws),
+                                                    getWReg(wt))),
+                                        binop(Iop_OrV128,
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN32Fx4,
+                                                                mkexpr(t1),
+                                                                mkexpr(t1)),
+                                                          binop(Iop_CmpLT32Fx4,
+                                                                mkexpr(t3),
+                                                                mkexpr(t1))),
+                                                    getWReg(wt)),
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN32Fx4,
+                                                                mkexpr(t2),
+                                                                mkexpr(t2)),
+                                                          binop(Iop_CmpLT32Fx4,
+                                                                mkexpr(t3),
+                                                                mkexpr(t2))),
+                                                    getWReg(ws))))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x8000000080000000),
+                                  mkU64(0x8000000080000000))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3), mkexpr(t4)));
+               break;
+            }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            case 0x01: { /* FMIN_A.D */
+               DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMINAD, 2);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_AndV128,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFFFFFFFFFF),
+                                  mkU64(0x7FFFFFFFFFFFFFFF))));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            getWReg(wt),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFFFFFFFFFF),
+                                  mkU64(0x7FFFFFFFFFFFFFFF))));
+               assign(t3,
+                      binop(Iop_Min64Fx2,
+                            mkexpr(t2), mkexpr(t1)));
+               assign(t4,
+                      binop(Iop_AndV128,
+                            binop(Iop_AndV128,
+                                  unop(Iop_NotV128,
+                                       binop(Iop_CmpUN64Fx2,
+                                             mkexpr(t3),
+                                             mkexpr(t3))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              binop(Iop_CmpEQ64Fx2,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2)),
+                                              binop(Iop_OrV128,
+                                                    getWReg(ws),
+                                                    getWReg(wt))),
+                                        binop(Iop_OrV128,
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN64Fx2,
+                                                                mkexpr(t1),
+                                                                mkexpr(t1)),
+                                                          binop(Iop_CmpLT64Fx2,
+                                                                mkexpr(t3),
+                                                                mkexpr(t1))),
+                                                    getWReg(wt)),
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN64Fx2,
+                                                                mkexpr(t2),
+                                                                mkexpr(t2)),
+                                                          binop(Iop_CmpLT64Fx2,
+                                                                mkexpr(t3),
+                                                                mkexpr(t2))),
+                                                    getWReg(ws))))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x8000000000000000),
+                                  mkU64(0x8000000000000000))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3), mkexpr(t4)));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x02: { /* DOTP_U.W */
-                     DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+      case 0x0E: { /* FMAX.df */
+         switch (df) {
+            case 0x00: { /* FMAX.W */
+               DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMAXW, 2);
+               putWReg(wd,
+                       binop(Iop_Max32Fx4,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+            case 0x01: { /* FMAX.D */
+               DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMAXW, 2);
+               putWReg(wd,
+                       binop(Iop_Max64Fx2,
+                             getWReg(ws),
+                             getWReg(wt)));
+               break;
+            }
 
-               case 0x03: { /* DOTP_U.D */
-                     DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(tmp[1]), mkexpr(tmp[0])));
-                     break;
-                  }
+      case 0x0F: { /* FMAX_A.df */
+         switch (df) {
+            case 0x00: { /* FMAX_A.W */
+               DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMAXAW, 2);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_AndV128,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFF7FFFFFFF),
+                                  mkU64(0x7FFFFFFF7FFFFFFF))));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            getWReg(wt),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFF7FFFFFFF),
+                                  mkU64(0x7FFFFFFF7FFFFFFF))));
+               assign(t3,
+                      binop(Iop_Max32Fx4,
+                            mkexpr(t2), mkexpr(t1)));
+               assign(t4,
+                      binop(Iop_AndV128,
+                            binop(Iop_AndV128,
+                                  unop(Iop_NotV128,
+                                       binop(Iop_CmpUN32Fx4,
+                                             mkexpr(t3),
+                                             mkexpr(t3))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              binop(Iop_CmpEQ32Fx4,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2)),
+                                              binop(Iop_AndV128,
+                                                    getWReg(ws),
+                                                    getWReg(wt))),
+                                        binop(Iop_OrV128,
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN32Fx4,
+                                                                mkexpr(t1),
+                                                                mkexpr(t1)),
+                                                          binop(Iop_CmpLT32Fx4,
+                                                                mkexpr(t1),
+                                                                mkexpr(t3))),
+                                                    getWReg(wt)),
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN32Fx4,
+                                                                mkexpr(t2),
+                                                                mkexpr(t2)),
+                                                          binop(Iop_CmpLT32Fx4,
+                                                                mkexpr(t2),
+                                                                mkexpr(t3))),
+                                                    getWReg(ws))))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x8000000080000000),
+                                  mkU64(0x8000000080000000))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3), mkexpr(t4)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FMAX_A.D */
+               DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FMAXAD, 2);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               assign(t1,
+                      binop(Iop_AndV128,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFFFFFFFFFF),
+                                  mkU64(0x7FFFFFFFFFFFFFFF))));
+               assign(t2,
+                      binop(Iop_AndV128,
+                            getWReg(wt),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FFFFFFFFFFFFFFF),
+                                  mkU64(0x7FFFFFFFFFFFFFFF))));
+               assign(t3,
+                      binop(Iop_Max64Fx2,
+                            mkexpr(t2), mkexpr(t1)));
+               assign(t4,
+                      binop(Iop_AndV128,
+                            binop(Iop_AndV128,
+                                  unop(Iop_NotV128,
+                                       binop(Iop_CmpUN64Fx2,
+                                             mkexpr(t3),
+                                             mkexpr(t3))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              binop(Iop_CmpEQ64Fx2,
+                                                    mkexpr(t1),
+                                                    mkexpr(t2)),
+                                              binop(Iop_AndV128,
+                                                    getWReg(ws),
+                                                    getWReg(wt))),
+                                        binop(Iop_OrV128,
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN64Fx2,
+                                                                mkexpr(t1),
+                                                                mkexpr(t1)),
+                                                          binop(Iop_CmpLT64Fx2,
+                                                                mkexpr(t1),
+                                                                mkexpr(t3))),
+                                                    getWReg(wt)),
+                                              binop(Iop_AndV128,
+                                                    binop(Iop_OrV128,
+                                                          binop(Iop_CmpUN64Fx2,
+                                                                mkexpr(t2),
+                                                                mkexpr(t2)),
+                                                          binop(Iop_CmpLT64Fx2,
+                                                                mkexpr(t2),
+                                                                mkexpr(t3))),
+                                                    getWReg(ws))))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x8000000000000000),
+                                  mkU64(0x8000000000000000))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t3), mkexpr(t4)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x02: { /* DPADD_S.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DPADD_S.H */
-                     DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      default:
+         return -1;
+   }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+   return 0;
+}
 
-                     putWReg(wd,
-                             binop(Iop_Add16x8,
-                                getWReg(wd),
-                                binop(Iop_64HLtoV128,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
-                     break;
-                  }
+static Int msa_3R_1C(UInt cins, UChar wd, UChar ws)   /* 3R (0x1C) */
+{
+   IRTemp t1, t2, t3, t4, t5, t6;
+   UShort operation;
+   UChar df, wt;
 
-               case 0x02: { /* DPADD_S.W */
-                     DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+   operation = (cins & 0x03C00000) >> 22;
+   df = (cins & 0x00200000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+   switch (operation) {
+      case 0x01: { /* FCOR.df */
+         switch (df) {
+            case 0x00: { /* FCOR.W */
+               DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCORW, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpUN32Fx4,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_Add32x4,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            case 0x01: { /* FCOR.D */
+               DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCORD, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpUN64Fx2,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-               case 0x03: { /* DPADD_S.D */
-                     DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_Add64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+      case 0x02: { /* FCUNE.df */
+         switch (df) {
+            case 0x00: { /* FCUNE.W */
+               DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUNEW, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpEQ32Fx4,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FCUNE.D */
+               DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCUNED, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpEQ64Fx2,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* DPADD_U.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DPADD_U.H */
-                     DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      case 0x03: { /* FCNE.df */
+         switch (df) {
+            case 0x00: { /* FCNE.W */
+               DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCNEW, 2);
+               putWReg(wd,
+                       binop(Iop_XorV128,
+                             unop(Iop_NotV128,
+                                  binop(Iop_CmpEQ32Fx4,
+                                        getWReg(ws),
+                                        getWReg(wt))),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            case 0x01: { /* FCNE.D */
+               DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FCNED, 2);
+               putWReg(wd,
+                       binop(Iop_XorV128,
+                             unop(Iop_NotV128,
+                                  binop(Iop_CmpEQ64Fx2,
+                                        getWReg(ws),
+                                        getWReg(wt))),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
+
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x04: { /* MUL_Q.df */
+         switch (df) {
+            case 0x00: { /* MUL_Q.H */
+               DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_QDMulHi16Sx8,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     putWReg(wd,
-                          binop(Iop_Add16x8,
-                                getWReg(wd),
-                                binop(Iop_64HLtoV128,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
-                     break;
-                  }
+            case 0x01: { /* MUL_Q.W */
+               DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3,
+                      binop(Iop_QDMulHi32Sx4,
+                            mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-               case 0x02: { /* DPADD_U.W */
-                     DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_Add32x4,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+      case 0x05: { /* MADD_Q.df */
+         switch (df) {
+            case 0x00: { /* MADD_Q.W */
+               DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(ws), mkU8(16)));
+               assign(t3, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(16)));
+               assign(t4, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(wt), mkU8(16)));
+               assign(t5,
+                      binop(Iop_Add32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        binop(Iop_InterleaveEvenLanes16x8,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t1), mkexpr(t3))));
+               assign(t6,
+                      binop(Iop_Add32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        getWReg(wd),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t2), mkexpr(t4))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes16x8,
+                             binop(Iop_QandQSarNnarrow32Sto16Sx4,
+                                   mkexpr(t6), mkU8(15)),
+                             binop(Iop_QandQSarNnarrow32Sto16Sx4,
+                                   mkexpr(t5), mkU8(15))));
+               break;
+            }
 
-               case 0x03: { /* DPADD_U.D */
-                     DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            case 0x01: { /* MADD_Q.W */
+               DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(ws), mkU8(32)));
+               assign(t3, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(32)));
+               assign(t4, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(wt), mkU8(32)));
+               assign(t5,
+                      binop(Iop_Add64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        binop(Iop_InterleaveEvenLanes32x4,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t3))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t3))))));
+               assign(t6,
+                      binop(Iop_Add64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        getWReg(wd),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t4))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t4))))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes32x4,
+                             binop(Iop_QandQSarNnarrow64Sto32Sx2,
+                                   mkexpr(t6), mkU8(31)),
+                             binop(Iop_QandQSarNnarrow64Sto32Sx2,
+                                   mkexpr(t5), mkU8(31))));
+               break;
+            }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            default:
+               return -1;
+         }
 
-                     putWReg(wd,
-                             binop(Iop_Add64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+         break;
+      }
 
-               default:
-                  return -1;
+      case 0x06: { /* MSUB_Q.df */
+         switch (df) {
+            case 0x00: { /* MSUB_Q.H */
+               DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(ws), mkU8(16)));
+               assign(t3, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(16)));
+               assign(t4, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(wt), mkU8(16)));
+               assign(t5,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        binop(Iop_InterleaveEvenLanes16x8,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t1), mkexpr(t3))));
+               assign(t6,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        getWReg(wd),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t2), mkexpr(t4))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes16x8,
+                             binop(Iop_QandQSarNnarrow32Sto16Sx4,
+                                   mkexpr(t6), mkU8(15)),
+                             binop(Iop_QandQSarNnarrow32Sto16Sx4,
+                                   mkexpr(t5), mkU8(15))));
+               break;
             }
 
-            break;
+            case 0x01: { /* MSUB_Q.W */
+               DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(ws), mkU8(32)));
+               assign(t3, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(32)));
+               assign(t4, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(wt), mkU8(32)));
+               assign(t5,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        binop(Iop_InterleaveEvenLanes32x4,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t3))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t3))))));
+               assign(t6,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        getWReg(wd),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t4))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t4))))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes32x4,
+                             binop(Iop_QandQSarNnarrow64Sto32Sx2,
+                                   mkexpr(t6), mkU8(31)),
+                             binop(Iop_QandQSarNnarrow64Sto32Sx2,
+                                   mkexpr(t5), mkU8(31))));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x04: { /* DPSUB_S.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DPSUB_S.H */
-                     DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      case 0x09: { /* FSOR.df */
+         switch (df) {
+            case 0x00: { /* FSOR.W */
+               DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSORW, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpUN32Fx4,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            case 0x01: { /* FSOR.D */
+               DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSORD, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpUN64Fx2,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-                     putWReg(wd,
-                          binop(Iop_Sub16x8,
-                                getWReg(wd),
-                                binop(Iop_64HLtoV128,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x02: { /* DPSUB_S.W */
-                     DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+      case 0x0A: { /* FSUNE.df */
+         switch (df) {
+            case 0x00: { /* FSUNE.W */
+               DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUNEW, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpEQ32Fx4,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_Sub32x4,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            case 0x01: { /* FSUNE.D */
+               DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSUNED, 2);
+               putWReg(wd,
+                       unop(Iop_NotV128,
+                            binop(Iop_CmpEQ64Fx2,
+                                  getWReg(ws),
+                                  getWReg(wt))));
+               break;
+            }
 
-               case 0x03: { /* DPSUB_S.D */
-                     DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullS32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_Sub64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+      case 0x0B: { /* FSNE.df */
+         switch (df) {
+            case 0x00: { /* FSNE.W */
+               DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSNEW, 2);
+               putWReg(wd,
+                       binop(Iop_XorV128,
+                             unop(Iop_NotV128,
+                                  binop(Iop_CmpEQ32Fx4,
+                                        getWReg(ws),
+                                        getWReg(wt))),
+                             binop(Iop_CmpUN32Fx4,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FSNE.D */
+               DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
+               calculateMSACSR(ws, wt, FSNED, 2);
+               putWReg(wd,
+                       binop(Iop_XorV128,
+                             unop(Iop_NotV128,
+                                  binop(Iop_CmpEQ64Fx2,
+                                        getWReg(ws),
+                                        getWReg(wt))),
+                             binop(Iop_CmpUN64Fx2,
+                                   getWReg(ws),
+                                   getWReg(wt))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x05: { /* DPSUB_U.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
+         break;
+      }
 
-            switch (df) {
-               case 0x01: { /* DPSUB_U.H */
-                     DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+      case 0x0C: { /* MULR_Q.df */
+         switch (df) {
+            case 0x00: { /* MULR_Q.H */
+               DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QRDMulHi16Sx8,
+                                mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_Add16,
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU8,
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+            case 0x01: { /* MULR_Q.W */
+               DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, getWReg(ws));
+               assign(t2, getWReg(wt));
+               assign(t3, binop(Iop_QRDMulHi32Sx4,
+                                mkexpr(t1), mkexpr(t2)));
+               putWReg(wd, mkexpr(t3));
+               break;
+            }
 
-                     putWReg(wd,
-                          binop(Iop_Sub16x8,
-                                getWReg(wd),
-                                binop(Iop_64HLtoV128,
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_32HLto64,
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_16HLto32,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
-                     break;
-                  }
+            default:
+               return -1;
+         }
 
-               case 0x02: { /* DPSUB_U.W */
-                     DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_Add32,
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU16,
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem16x8,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+      case 0x0D: { /* MADDR_Q.df */
+         switch (df) {
+            case 0x00: { /* MADDR_Q.W */
+               DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(ws), mkU8(16)));
+               assign(t3, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(16)));
+               assign(t4, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(wt), mkU8(16)));
+               assign(t5,
+                      binop(Iop_Add32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        binop(Iop_InterleaveEvenLanes16x8,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t1), mkexpr(t3))));
+               assign(t6,
+                      binop(Iop_Add32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        getWReg(wd),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t2), mkexpr(t4))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes16x8,
+                             binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+                                   mkexpr(t6), mkU8(15)),
+                             binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+                                   mkexpr(t5), mkU8(15))));
+               break;
+            }
 
-                     putWReg(wd,
-                             binop(Iop_Sub32x4,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+            case 0x01: { /* MADDR_Q.D */
+               DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(ws), mkU8(32)));
+               assign(t3, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(32)));
+               assign(t4, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(wt), mkU8(32)));
+               assign(t5,
+                      binop(Iop_Add64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        binop(Iop_InterleaveEvenLanes32x4,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t3))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t3))))));
+               assign(t6,
+                      binop(Iop_Add64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        getWReg(wd),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t4))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t4))))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes32x4,
+                             binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+                                   mkexpr(t6), mkU8(31)),
+                             binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+                                   mkexpr(t5), mkU8(31))));
+               break;
+            }
 
-               case 0x03: { /* DPSUB_U.D */
-                     DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
+            default:
+               return -1;
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_Add64,
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i))),
-                                     binop(Iop_MullU32,
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t1),
-                                                 mkU8(2 * i + 1)),
-                                           binop(Iop_GetElem32x4,
-                                                 mkexpr(t2),
-                                                 mkU8(2 * i + 1)))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_Sub64x2,
-                                   getWReg(wd),
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+      case 0x0E: { /* MSUBR_Q.df */
+         switch (df) {
+            case 0x00: { /* MSUBR_Q.W */
+               DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(ws), mkU8(16)));
+               assign(t3, // even
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveEvenLanes16x8,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(16)));
+               assign(t4, // odd
+                      binop(Iop_SarN32x4,
+                            getWReg(wt), mkU8(16)));
+               assign(t5,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        binop(Iop_InterleaveEvenLanes16x8,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t1), mkexpr(t3))));
+               assign(t6,
+                      binop(Iop_Sub32x4,
+                            binop(Iop_ShlN32x4,
+                                  binop(Iop_SarN32x4,
+                                        getWReg(wd),
+                                        mkU8(16)),
+                                  mkU8(15)),
+                            binop(Iop_Mul32x4,
+                                  mkexpr(t2), mkexpr(t4))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes16x8,
+                             binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+                                   mkexpr(t6), mkU8(15)),
+                             binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+                                   mkexpr(t5), mkU8(15))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* MSUBR_Q.D */
+               DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               t5 = newTemp(Ity_V128);
+               t6 = newTemp(Ity_V128);
+               assign(t1, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(ws), mkU8(32)));
+               assign(t3, // even
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveEvenLanes32x4,
+                                  getWReg(wt),
+                                  getWReg(wt)),
+                            mkU8(32)));
+               assign(t4, // odd
+                      binop(Iop_SarN64x2,
+                            getWReg(wt), mkU8(32)));
+               assign(t5,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        binop(Iop_InterleaveEvenLanes32x4,
+                                              getWReg(wd),
+                                              getWReg(wd)),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t3))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t1)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t3))))));
+               assign(t6,
+                      binop(Iop_Sub64x2,
+                            binop(Iop_ShlN64x2,
+                                  binop(Iop_SarN64x2,
+                                        getWReg(wd),
+                                        mkU8(32)),
+                                  mkU8(31)),
+                            binop(Iop_64HLtoV128,
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128HIto64,
+                                             mkexpr(t4))),
+                                  binop(Iop_Mul64,
+                                        unop(Iop_V128to64,
+                                             mkexpr(t2)),
+                                        unop(Iop_V128to64,
+                                             mkexpr(t4))))));
+               putWReg(wd,
+                       binop(Iop_InterleaveEvenLanes32x4,
+                             binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+                                   mkexpr(t6), mkU8(31)),
+                             binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+                                   mkexpr(t5), mkU8(31))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
+         break;
+      }
+
       default:
          return -1;
    }
@@ -19219,1563 +13749,1331 @@ static Int msa_3R_13(UInt cins, UChar wd, UChar ws) { /* 3R (0x13) */
    return 0;
 }
 
-static Int msa_3R_14(UInt cins, UChar wd, UChar ws) { /* 3R (0x14) */
-   IRTemp t1, t2, t3, t4;
+static Int msa_ELM(UInt cins, UChar wd, UChar ws)   /* ELM (0x19) */
+{
+   IRTemp t1, t2, t3, t4, t5;
    IRType ty;
    UShort operation;
-   UChar df, wt;
+   UChar df, n;
+
+   operation = (cins & 0x03C00000) >> 22;
+   ty = mode64 ? Ity_I64 : Ity_I32;
+
+   switch ((cins & 0x03FF0000) >> 16) {
+      case 0x07E: /* CFCMSA */
+         DIP("CFCMSA r%d, c%d", wd, ws);
+
+         switch (ws) {
+            case 0: { /* MSAIR */
+               IRDirty *d;
+               t1 = newTemp(Ity_I32);
+               /* IRExpr_BBPTR() =>
+                                    Need to pass pointer to
+                                          guest state to helper. */
+               d = unsafeIRDirty_1_N(t1, 0,
+                                     "mips_dirtyhelper_get_MSAIR",
+                                     &mips_dirtyhelper_get_MSAIR,
+                                     mkIRExprVec_0());
+               /* d->nFxState = 0; */
+               stmt(IRStmt_Dirty(d));
+               putIReg(wd,
+                       mkWidenFrom32(ty, mkexpr(t1), True));
+               break;
+            }
+
+            case 1: /* MSACSR */
+               putIReg(wd,
+                       mkWidenFrom32(ty, getMSACSR(), True));
+               break;
+
+            default:
+               putIReg(wd,
+                       mkWidenFrom32(ty, mkU32(0), False));
+               break;
+         }
+
+         break;
+
+      case 0x03E: /* CTCMSA */
+         DIP("CTCMSA r%d, c%d", ws, wd);
+
+         if (wd == 1) { /* MSACSR */
+            putMSACSR(
+               binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
+                     mkU32(0x1FFFFFF)));
+         }
+
+         break;
+
+      case 0x0BE: /* MOVE.V */
+         DIP("MOVE.V w%d, w%d", ws, wd);
+         putWReg(wd, getWReg(ws));
+         break;
+
+      default:
+         df = (cins & 0x003F0000) >> 16;
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
-   ty = mode64 ? Ity_I64 : Ity_I32;
+         if ((df & 0x38) == 0x38) {        // 11100n; dw
+            n = df & 0x01;
+            df = 0x38;
+         } else if ((df & 0x30) == 0x30) { // 1100nn; w
+            n = df & 0x03;
+            df = 0x30;
+         } else if ((df & 0x20) == 0x20) { // 100nnn; hw
+            n = df & 0x07;
+            df = 0x20;
+         } else if ((df & 0x00) == 0x00) { // 00nnnn; b
+            n = df & 0x0F;
+            df = 0x00;
+         }
 
-   switch (operation) {
-      case 0x00: { /* SLD.df */
-            switch (df) {
-               case 0x00: {
-                     DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
-                     t1 = newTemp(Ity_I32);
+         switch (operation) {
+            case 0x00: /* SLDI.df */
+               switch (df) {
+                  case 0x00: /* SLDI.B */
+                     DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
+                     t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
                      assign(t1,
-                            binop(Iop_Shl32,
-                                  binop(Iop_And32,
-                                        mkNarrowTo32(ty,
-                                                     getIReg(wt)),
-                                        mkU32(15)),
-                                  mkU8(3)));
-                     assign(t2,
                             binop(Iop_ShrV128,
                                   getWReg(ws),
-                                  unop(Iop_32to8, mkexpr(t1))));
-                     assign(t3,
+                                  mkU8(n << 3)));
+                     assign(t2,
                             binop(Iop_ShlV128,
                                   getWReg(wd),
-                                  unop(Iop_32to8,
-                                       binop(Iop_Sub32,
-                                             mkU32(128),
-                                             mkexpr(t1)))));
+                                  mkU8(n ?
+                                       (16 - n) << 3 : 0)));
                      putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t2), mkexpr(t3)));
+                             binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
                      break;
-                  }
 
-               case 0x01: {/* SLD.H */
-                     DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shl32,
-                                  binop(Iop_And32,
-                                        mkNarrowTo32(ty,
-                                                     getIReg(wt)),
-                                        mkU32(7)),
-                                  mkU8(3)));
-                     assign(t2,
-                            binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
-                     assign(t3,
-                            binop(Iop_Shr64x2,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkexpr(t2), mkexpr(t2))));
-                     assign(t4,
-                            binop(Iop_Shl64x2,
-                                  getWReg(wd),
-                                  binop(Iop_Sub64x2,
-                                        binop(Iop_64HLtoV128,
-                                              mkU64(0x40ul),
-                                              mkU64(0x40ul)),
-                                        binop(Iop_64HLtoV128,
-                                              mkexpr(t2),
-                                              mkexpr(t2)))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3),
-                                   IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            mkexpr(t1), mkU32(0)),
-                                      mkexpr(t4),
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(0), mkU64(0)))));
-                     break;
-                  }
+                  case 0x20: /* SLDI.H */
+                     DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
 
-               case 0x02: {/* SLD.W */
-                     DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shl32,
-                                  binop(Iop_And32,
-                                        mkNarrowTo32(ty,
-                                                     getIReg(wt)),
-                                        mkU32(3)),
-                                  mkU8(3)));
-                     assign(t2,
-                            binop(Iop_32HLto64,
-                                  mkexpr(t1), mkexpr(t1)));
-                     assign(t3,
-                            binop(Iop_Shr32x4,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkexpr(t2), mkexpr(t2))));
-                     assign(t4,
-                            binop(Iop_Shl32x4,
-                                  getWReg(wd),
-                                  binop(Iop_Sub32x4,
-                                        binop(Iop_64HLtoV128,
-                                              mkU64(0x2000000020ul),
-                                              mkU64(0x2000000020ul)),
-                                        binop(Iop_64HLtoV128,
-                                              mkexpr(t2),
-                                              mkexpr(t2)))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3),
-                                   IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            mkexpr(t1), mkU32(0)),
-                                      mkexpr(t4),
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(0), mkU64(0)))));
-                     break;
-                  }
+                     if (n == 0) {
+                        putWReg(wd, getWReg(ws));
+                     } else {
+                        t1 = newTemp(Ity_V128);
+                        t2 = newTemp(Ity_V128);
+                        assign(t1,
+                               binop(Iop_ShrN64x2,
+                                     getWReg(ws),
+                                     mkU8(n << 3)));
+                        assign(t2,
+                               binop(Iop_ShlN64x2,
+                                     getWReg(wd),
+                                     mkU8((8 - n) << 3)));
+                        putWReg(wd,
+                                binop(Iop_OrV128,
+                                      mkexpr(t1),
+                                      mkexpr(t2)));
+                     }
 
-               case 0x03: { /* SLD.D */
-                     DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shl32,
-                                  binop(Iop_And32,
-                                        mkNarrowTo32(ty,
-                                                     getIReg(wt)),
-                                        mkU32(1)),
-                                  mkU8(3)));
-                     assign(t2,
-                            binop(Iop_32HLto64,
-                                  binop(Iop_Or32,
-                                        mkexpr(t1),
-                                        binop(Iop_Shl32,
-                                              mkexpr(t1), mkU8(16))),
-                                  binop(Iop_Or32,
-                                        mkexpr(t1),
-                                        binop(Iop_Shl32,
-                                              mkexpr(t1), mkU8(16)))));
-                     assign(t3,
-                            binop(Iop_Shr16x8,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkexpr(t2), mkexpr(t2))));
-                     assign(t4,
-                            binop(Iop_Shl16x8,
-                               getWReg(wd),
-                               binop(Iop_Sub16x8,
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0x10001000100010ul),
-                                           mkU64(0x10001000100010ul)),
-                                     binop(Iop_64HLtoV128,
-                                           mkexpr(t2),
-                                           mkexpr(t2)))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3),
-                                   IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            mkexpr(t1), mkU32(0)),
-                                      mkexpr(t4),
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(0), mkU64(0)))));
                      break;
-                  }
-            }
-
-            break;
-         }
-
-      case 0x01: { /* SPLAT.df */
-            switch (df) {
-                  Int i;
 
-               case 0x00: { /* SPLAT.B */
-                     DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I32);
-                     assign(t1, getWReg(ws));
-                     assign(t2,
-                            mkNarrowTo32(ty, getIReg(wt)));
-                     IRTemp tmp[16];
+                  case 0x30: /* SLDI.W */
+                     DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I8);
-                        assign(tmp[i],
-                               binop(Iop_GetElem8x16,
-                                     mkexpr(t1),
-                                     unop(Iop_32to8, mkexpr(t2))));
+                     if (n == 0) {
+                        putWReg(wd, getWReg(ws));
+                     } else {
+                        t1 = newTemp(Ity_V128);
+                        t2 = newTemp(Ity_V128);
+                        assign(t1,
+                               binop(Iop_ShrN32x4,
+                                     getWReg(ws),
+                                     mkU8(n << 3)));
+                        assign(t2,
+                               binop(Iop_ShlN32x4,
+                                     getWReg(wd),
+                                     mkU8((4 - n) << 3)));
+                        putWReg(wd,
+                                binop(Iop_OrV128,
+                                      mkexpr(t1),
+                                      mkexpr(t2)));
                      }
 
-                     putWReg(wd,
-                          binop(Iop_64HLtoV128,
-                                binop(Iop_32HLto64,
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[15]),
-                                                  mkexpr(tmp[14])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[13]),
-                                                  mkexpr(tmp[12]))),
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[11]),
-                                                  mkexpr(tmp[10])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[9]),
-                                                  mkexpr(tmp[8])))),
-                                binop(Iop_32HLto64,
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
                      break;
-                  }
 
-               case 0x01: { /* SPLAT.H */
-                     DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I32);
-                     assign(t1, getWReg(ws));
-                     assign(t2,
-                            mkNarrowTo32(ty, getIReg(wt)));
-                     IRTemp tmp[8];
+                  case 0x38:  /* SLDI.D */
+                     DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               binop(Iop_GetElem16x8,
-                                     mkexpr(t1),
-                                     unop(Iop_32to8, mkexpr(t2))));
+                     if (n == 0) {
+                        putWReg(wd, getWReg(ws));
+                     } else {
+                        t1 = newTemp(Ity_V128);
+                        t2 = newTemp(Ity_V128);
+                        assign(t1,
+                               binop(Iop_ShrN16x8,
+                                     getWReg(ws),
+                                     mkU8(n << 3)));
+                        assign(t2,
+                               binop(Iop_ShlN16x8,
+                                     getWReg(wd),
+                                     mkU8((2 - n) << 3)));
+                        putWReg(wd,
+                                binop(Iop_OrV128,
+                                      mkexpr(t1),
+                                      mkexpr(t2)));
                      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
                      break;
-                  }
-
-               case 0x02: { /* SPLAT.W */
-                     DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I32);
-                     assign(t1, getWReg(ws));
-                     assign(t2,
-                            mkNarrowTo32(ty, getIReg(wt)));
-                     IRTemp tmp[4];
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               binop(Iop_GetElem32x4,
-                                     mkexpr(t1),
-                                     unop(Iop_32to8, mkexpr(t2))));
-                     }
+                  default:
+                     return -1;
+               }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
-                     break;
-                  }
+               break;
 
-               case 0x03: { /* SPLAT.D */
-                     DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
+            case 0x01: /* SPLATI.df */
+               switch (df) {
+                  case 0x00: { /* SPLATI.B */
+                     DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
                      t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I32);
-                     assign(t1, getWReg(ws));
-                     assign(t2,
-                            mkNarrowTo32(ty, getIReg(wt)));
-                     IRTemp tmp[2];
+                     t2 = newTemp(Ity_V128);
+                     t3 = newTemp(Ity_V128);
+                     t4 = newTemp(Ity_V128);
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               binop(Iop_GetElem64x2,
-                                     mkexpr(t1),
-                                     unop(Iop_32to8, mkexpr(t2))));
-                     }
+                     if (n & 1)
+                        assign(t1,
+                               binop(Iop_InterleaveOddLanes8x16,
+                                     getWReg(ws),
+                                     getWReg(ws)));
+                     else
+                        assign(t1,
+                               binop(Iop_InterleaveEvenLanes8x16,
+                                     getWReg(ws),
+                                     getWReg(ws)));
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(tmp[1]), mkexpr(tmp[0])));
-                     break;
-                  }
-            }
+                     n /= 2;
 
-            break;
-         }
+                     if (n & 1)
+                        assign(t2,
+                               binop(Iop_InterleaveOddLanes16x8,
+                                     mkexpr(t1), mkexpr(t1)));
+                     else
+                        assign(t2,
+                               binop(Iop_InterleaveEvenLanes16x8,
+                                     mkexpr(t1), mkexpr(t1)));
 
-      case 0x02: { /* PCKEV.df */
-            switch (df) {
-               case 0x00: { /* PCKEV.B */
-                     DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackEvenLanes8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
+                     n /= 2;
+
+                     if (n & 1)
+                        assign(t3,
+                               binop(Iop_InterleaveOddLanes32x4,
+                                     mkexpr(t2), mkexpr(t2)));
+                     else
+                        assign(t3,
+                               binop(Iop_InterleaveEvenLanes32x4,
+                                     mkexpr(t2), mkexpr(t2)));
+
+                     n /= 2;
+
+                     if (n & 1)
+                        assign(t4,
+                               binop(Iop_InterleaveHI64x2,
+                                     mkexpr(t3), mkexpr(t3)));
+                     else
+                        assign(t4,
+                               binop(Iop_InterleaveLO64x2,
+                                     mkexpr(t3), mkexpr(t3)));
+
+                     putWReg(wd, mkexpr(t4));
                      break;
                   }
 
-               case 0x01: { /* PCKEV.H */
-                     DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
+                  case 0x20: { /* SPLATI.H */
+                     DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
                      t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackEvenLanes16x8,
-                                  mkexpr(t1), mkexpr(t2)));
+
+                     if (n & 1)
+                        assign(t1,
+                               binop(Iop_InterleaveOddLanes16x8,
+                                     getWReg(ws),
+                                     getWReg(ws)));
+                     else
+                        assign(t1,
+                               binop(Iop_InterleaveEvenLanes16x8,
+                                     getWReg(ws),
+                                     getWReg(ws)));
+
+                     n /= 2;
+
+                     if (n & 1)
+                        assign(t2,
+                               binop(Iop_InterleaveOddLanes32x4,
+                                     mkexpr(t1), mkexpr(t1)));
+                     else
+                        assign(t2,
+                               binop(Iop_InterleaveEvenLanes32x4,
+                                     mkexpr(t1), mkexpr(t1)));
+
+                     n /= 2;
+
+                     if (n & 1)
+                        assign(t3,
+                               binop(Iop_InterleaveHI64x2,
+                                     mkexpr(t2), mkexpr(t2)));
+                     else
+                        assign(t3,
+                               binop(Iop_InterleaveLO64x2,
+                                     mkexpr(t2), mkexpr(t2)));
+
                      putWReg(wd, mkexpr(t3));
                      break;
                   }
 
-               case 0x02: { /* PCKEV.W */
-                     DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
+                  case 0x30: { /* SPLATI.W */
+                     DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
                      t3 = newTemp(Ity_V128);
                      assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackEvenLanes32x4,
-                                  mkexpr(t1), mkexpr(t2)));
+
+                     if (n & 1)
+                        assign(t2,
+                               binop(Iop_InterleaveOddLanes32x4,
+                                     mkexpr(t1), mkexpr(t1)));
+                     else
+                        assign(t2,
+                               binop(Iop_InterleaveEvenLanes32x4,
+                                     mkexpr(t1), mkexpr(t1)));
+
+                     n /= 2;
+
+                     if (n & 1)
+                        assign(t3,
+                               binop(Iop_InterleaveHI64x2,
+                                     mkexpr(t2), mkexpr(t2)));
+                     else
+                        assign(t3,
+                               binop(Iop_InterleaveLO64x2,
+                                     mkexpr(t2), mkexpr(t2)));
+
                      putWReg(wd, mkexpr(t3));
                      break;
                   }
 
-               case 0x03: { /* PCKEV.D */
-                     DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
+                  case 0x38: /* SPLATI.D */
+                     DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
                      t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
                      t3 = newTemp(Ity_V128);
                      assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO64x2,
-                                  mkexpr(t1), mkexpr(t2)));
+
+                     if (n)
+                        assign(t3,
+                               binop(Iop_InterleaveHI64x2,
+                                     mkexpr(t1), mkexpr(t1)));
+                     else
+                        assign(t3,
+                               binop(Iop_InterleaveLO64x2,
+                                     mkexpr(t1), mkexpr(t1)));
+
                      putWReg(wd, mkexpr(t3));
                      break;
-                  }
 
-               default:
-                  return -1;
-            }
+                  default:
+                     return -1;
+               }
 
-            break;
-         }
+               break;
 
-      case 0x03: { /* PCKOD.df */
-            switch (df) {
-               case 0x00: { /* PCKOD.B */
-                     DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackOddLanes8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
+            case 0x02: /* COPY_S.df */
+               switch (df) {
+                  case 0x00: /* COPY_S.B */
+                     DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
+                     t1 = newTemp(Ity_I8);
+
+                     switch (n) {
+                        case 0:
+                           assign(t1,
+                                  unop(Iop_32to8,
+                                       unop(Iop_V128to32,
+                                            getWReg(ws))));
+                           break;
+
+                        case 1:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_V128to32,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 2:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 3:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 4:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 5:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 6:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 7:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 8:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 9:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 10:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 11:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 12:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 13:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 14:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 15:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
+                     }
+
+                     putIReg(wd,
+                             unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
+                                  mkexpr(t1)));
                      break;
-                  }
 
-               case 0x01: { /* PCKOD.H */
-                     DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackOddLanes16x8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                  case 0x20: /* COPY_S.H */
+                     DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
+                     t1 = newTemp(Ity_I16);
+
+                     switch (n) {
+                        case 0:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 1:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 2:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 3:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
 
-               case 0x02: { /* PCKOD.W */
-                     DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_PackOddLanes32x4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 4:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
 
-               case 0x03: { /* PCKOD.D */
-                     DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI64x2,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 5:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
 
-               default:
-                  return -1;
-            }
+                        case 6:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
 
-            break;
-         }
+                        case 7:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
+                     }
 
-      case 0x04: { /* ILVL.df */
-            switch (df) {
-               case 0x00: { /* ILVL.B */
-                     DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
+                     putIReg(wd,
+                             unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
+                                  mkexpr(t1)));
                      break;
-                  }
 
-               case 0x01: { /* ILVL.H */
-                     DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI16x8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                  case 0x30: /* COPY_S.W */
+                     DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
 
-               case 0x02: { /* ILVL.W */
-                     DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI32x4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                     switch (n) {
+                        case 0:
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_V128to32,
+                                                      getWReg(ws)),
+                                                 True));
+                           break;
 
-               case 0x03: { /* ILVL.D */
-                     DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI64x2,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 1:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128to64, getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64HIto32,
+                                                      mkexpr(t2)),
+                                                 True));
+                           break;
 
-               default:
-                  return -1;
-            }
+                        case 2:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128HIto64,
+                                       getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64to32,
+                                                      mkexpr(t2)),
+                                                 True));
+                           break;
 
-            break;
-         }
+                        case 3:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128HIto64,
+                                       getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64HIto32,
+                                                      mkexpr(t2)),
+                                                 True));
+                           break;
 
-      case 0x05: { /* ILVR.df */
-            switch (df) {
-               case 0x00: { /* ILVL.B */
-                     DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        default:
+                           break;
+                     }
 
-               case 0x01: { /* ILVL.H */
-                     DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO16x8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
                      break;
-                  }
 
-               case 0x02: { /* ILVL.W */
-                     DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO32x4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                  case 0x38: /* COPY_S.D */
+                     if (mode64) {
+                        DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
 
-               case 0x03: { /* ILVL.D */
-                     DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO64x2,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
-            }
+                        switch (n) {
+                           case 0:
+                              putIReg(wd,
+                                      unop(Iop_V128to64,
+                                           getWReg(ws)));
+                              break;
 
-            break;
-         }
+                           case 1:
+                              putIReg(wd,
+                                      unop(Iop_V128HIto64,
+                                           getWReg(ws)));
+                              break;
+                        }
+                     } else {
+                        return -2;
+                     }
 
-      case 0x06: { /* ILVEV.df */
-            switch (df) {
-               case 0x00: { /* ILVEV.B */
-                     DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveEvenLanes8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
                      break;
-                  }
 
-               case 0x01: { /* ILVEV.H */
-                     DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveEvenLanes16x8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                  default:
+                     return -1;
+               }
 
-               case 0x02: { /* ILVEV.W */
-                     DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveEvenLanes32x4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+               break;
 
-               case 0x03: { /* ILVEV.D */
-                     DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveLO64x2,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+            case 0x03: { /* COPY_U.df */
+               switch (df) {
+                  case 0x00: /* COPY_U.B */
+                     DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
+                     t1 = newTemp(Ity_I8);
 
-               default:
-                  return -1;
-            }
+                     switch (n) {
+                        case 0:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
+
+                        case 1:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-            break;
-         }
+                        case 2:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-      case 0x07: { /* ILVOD.df */
-            switch (df) {
-               case 0x00: { /* ILVOD.B */
-                     DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveOddLanes8x16,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 3:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-               case 0x01: { /* ILVOD.H */
-                     DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveOddLanes16x8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 4:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-               case 0x02: { /* ILVOD.W */
-                     DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveOddLanes32x4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 5:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-               case 0x03: { /* ILVOD.D */
-                     DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_InterleaveHI64x2,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                        case 6:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-               default:
-                  return -1;
-            }
+                        case 7:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128to64,
+                                                      getWReg(ws))))));
+                           break;
 
-            break;
-         }
+                        case 8:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-      default:
-         return -1;
-   }
+                        case 9:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-   return 0;
-}
+                        case 10:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-static Int msa_3R_15(UInt cins, UChar wd, UChar ws) { /* 3R (0x15) */
-   IRTemp t1, t2, t3, t4;
-   UShort operation;
-   UChar df, wt;
+                        case 11:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64to32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-   operation = (cins & 0x03800000) >> 23;
-   df = (cins & 0x00600000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+                        case 12:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-   switch (operation) {
-      case 0x00: { /* VSHF.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1, getWReg(wd));
-            assign(t2, getWReg(ws));
-            assign(t3, getWReg(wt));
+                        case 13:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32to16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-            switch (df) {
-               case 0x00: { /* VSHF.B */
-                     DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[16];
-                     Int i;
+                        case 14:
+                           assign(t1,
+                                  unop(Iop_16to8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
 
-                     for (i = 0; i < 16; i++) {
-                        tmp[i] = newTemp(Ity_I8);
-                        assign(tmp[i],
-                               IRExpr_ITE(
-                                  binop(Iop_CmpEQ8,
-                                        binop(Iop_And8,
-                                              binop(Iop_GetElem8x16,
-                                                    mkexpr(t1),
-                                                    mkU8(i)),
-                                              mkU8(0xC0)),
-                                        mkU8(0x0)),
-                                  IRExpr_ITE(
-                                     binop(Iop_CmpEQ8,
-                                           binop(Iop_And8,
-                                                 binop(Iop_GetElem8x16,
-                                                       mkexpr(t1),
-                                                       mkU8(i)),
-                                                 mkU8(0x10)),
-                                           mkU8(0x0)),
-                                     binop(Iop_GetElem8x16,
-                                           mkexpr(t3),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(i))),
-                                     binop(Iop_GetElem8x16,
-                                           mkexpr(t2),
-                                           binop(Iop_GetElem8x16,
-                                                 mkexpr(t1),
-                                                 mkU8(i)))),
-                                  mkU8(0x0)));
+                        case 15:
+                           assign(t1,
+                                  unop(Iop_16HIto8,
+                                       unop(Iop_32HIto16,
+                                            unop(Iop_64HIto32,
+                                                 unop(Iop_V128HIto64,
+                                                      getWReg(ws))))));
+                           break;
                      }
 
-                     putWReg(wd,
-                          binop(Iop_64HLtoV128,
-                                binop(Iop_32HLto64,
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[15]),
-                                                  mkexpr(tmp[14])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[13]),
-                                                  mkexpr(tmp[12]))),
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[11]),
-                                                  mkexpr(tmp[10])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[9]),
-                                                  mkexpr(tmp[8])))),
-                                binop(Iop_32HLto64,
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[7]),
-                                                  mkexpr(tmp[6])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[5]),
-                                                  mkexpr(tmp[4]))),
-                                      binop(Iop_16HLto32,
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[3]),
-                                                  mkexpr(tmp[2])),
-                                            binop(Iop_8HLto16,
-                                                  mkexpr(tmp[1]),
-                                                  mkexpr(tmp[0]))))));
+                     putIReg(wd,
+                             unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
+                                  mkexpr(t1)));
                      break;
-                  }
 
-               case 0x01: { /* VSHF.H */
-                     DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[8];
-                     Int i;
+                  case 0x20: /* COPY_U.H */
+                     DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
+                     t1 = newTemp(Ity_I16);
 
-                     for (i = 0; i < 8; i++) {
-                        tmp[i] = newTemp(Ity_I16);
-                        assign(tmp[i],
-                               IRExpr_ITE(
-                                  binop(Iop_CmpEQ16,
-                                        binop(Iop_And16,
-                                              binop(Iop_GetElem16x8,
-                                                    mkexpr(t1),
-                                                    mkU8(i)),
-                                              mkU16(0xC0)),
-                                        mkU16(0x0)),
-                                  IRExpr_ITE(
-                                     binop(Iop_CmpEQ16,
-                                           binop(Iop_And16,
-                                                 binop(Iop_GetElem16x8,
-                                                       mkexpr(t1),
-                                                       mkU8(i)),
-                                                 mkU16(0x08)),
-                                           mkU16(0x0)),
-                                     binop(Iop_GetElem16x8,
-                                           mkexpr(t3),
-                                           unop(Iop_16to8,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t1),
-                                                      mkU8(i)))),
-                                     binop(Iop_GetElem16x8,
-                                           mkexpr(t2),
-                                           unop(Iop_16to8,
-                                                binop(Iop_GetElem16x8,
-                                                      mkexpr(t1),
-                                                      mkU8(i))))),
-                                  mkU16(0x0)));
-                     }
+                     switch (n) {
+                        case 0:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[7]),
-                                               mkexpr(tmp[6])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[5]),
-                                               mkexpr(tmp[4]))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_16HLto32,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0])))));
-                     break;
-                  }
+                        case 1:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 2:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 3:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128to64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 4:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
+
+                        case 5:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64to32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
 
-               case 0x02: { /* VSHF.W */
-                     DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[4];
-                     Int i;
+                        case 6:
+                           assign(t1,
+                                  unop(Iop_32to16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                               IRExpr_ITE(
-                                  binop(Iop_CmpEQ32,
-                                        binop(Iop_And32,
-                                              binop(Iop_GetElem32x4,
-                                                    mkexpr(t1),
-                                                    mkU8(i)),
-                                              mkU32(0xC0)),
-                                        mkU32(0x0)),
-                                  IRExpr_ITE(
-                                     binop(Iop_CmpEQ32,
-                                           binop(Iop_And32,
-                                                 binop(Iop_GetElem32x4,
-                                                       mkexpr(t1),
-                                                       mkU8(i)),
-                                                 mkU32(0x04)),
-                                           mkU32(0x0)),
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t3),
-                                           unop(Iop_32to8,
-                                                binop(Iop_GetElem32x4,
-                                                      mkexpr(t1),
-                                                      mkU8(i)))),
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t2),
-                                           unop(Iop_32to8,
-                                                binop(Iop_GetElem32x4,
-                                                      mkexpr(t1),
-                                                      mkU8(i))))),
-                                  mkU32(0x0)));
+                        case 7:
+                           assign(t1,
+                                  unop(Iop_32HIto16,
+                                       unop(Iop_64HIto32,
+                                            unop(Iop_V128HIto64,
+                                                 getWReg(ws)))));
+                           break;
                      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[3]),
-                                         mkexpr(tmp[2])),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0]))));
+                     putIReg(wd,
+                             unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
+                                  mkexpr(t1)));
                      break;
-                  }
-
-               case 0x03: { /* VSHF.D */
-                     DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
-                     IRTemp tmp[2];
-                     Int i;
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                               IRExpr_ITE(
-                                  binop(Iop_CmpEQ64,
-                                        binop(Iop_And64,
-                                              binop(Iop_GetElem64x2,
-                                                    mkexpr(t1),
-                                                    mkU8(i)),
-                                              mkU64(0xC0)),
-                                        mkU64(0x0)),
-                                  IRExpr_ITE(
-                                     binop(Iop_CmpEQ64,
-                                           binop(Iop_And64,
-                                                 binop(Iop_GetElem64x2,
-                                                       mkexpr(t1),
-                                                       mkU8(i)),
-                                                 mkU64(0x02)),
-                                           mkU64(0x0)),
-                                     binop(Iop_GetElem64x2,
-                                           mkexpr(t3),
-                                           unop(Iop_64to8,
-                                                binop(Iop_GetElem64x2,
-                                                      mkexpr(t1),
-                                                      mkU8(i)))),
-                                     binop(Iop_GetElem64x2,
-                                           mkexpr(t2),
-                                           unop(Iop_64to8,
-                                                binop(Iop_GetElem64x2,
-                                                      mkexpr(t1),
-                                                      mkU8(i))))),
-                                  mkU64(0x0)));
-                     }
+                  case 0x30: /* COPY_U.W */
+                     DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(tmp[1]), mkexpr(tmp[0])));
-                     break;
-                  }
+                     switch (n) {
+                        case 0:
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_V128to32,
+                                                      getWReg(ws)),
+                                                 False));
+                           break;
 
-               default:
-                  return -1;
-            }
+                        case 1:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128to64,
+                                       getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64HIto32,
+                                                      mkexpr(t2)),
+                                                 False));
+                           break;
 
-            break;
-         }
+                        case 2:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128HIto64,
+                                       getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64to32,
+                                                      mkexpr(t2)),
+                                                 False));
+                           break;
 
-      case 0x01: { /* SRAR.df */
-            switch (df) {
-               case 0x00: { /* SRAR.B */
-                     DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Sar8x16,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x808080808080808ull),
-                                        mkU64(0x808080808080808ull)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ8x16,
-                                       binop(Iop_ShlN8x16,
-                                             getWReg(wt),
-                                             mkU8(5)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN8x16,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl8x16,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(7)));
-                     putWReg(wd,
-                             binop(Iop_Add8x16,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
+                        case 3:
+                           t2 = newTemp(Ity_I64);
+                           assign(t2,
+                                  unop(Iop_V128HIto64,
+                                       getWReg(ws)));
+                           putIReg(wd,
+                                   mkWidenFrom32(ty,
+                                                 unop(Iop_64HIto32,
+                                                      mkexpr(t2)),
+                                                 False));
+                           break;
 
-               case 0x01: { /* SRAR.H */
-                     DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Sar16x8,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x10001000100010ul),
-                                        mkU64(0x10001000100010ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ16x8,
-                                       binop(Iop_ShlN16x8,
-                                             getWReg(wt),
-                                             mkU8(12)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN16x8,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl16x8,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(15)));
-                     putWReg(wd,
-                             binop(Iop_Add16x8,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
+                        default:
+                           break;
+                     }
 
-               case 0x02: { /* SRAR.W */
-                     DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128); // shifted
-                     t2 = newTemp(Ity_V128); // 32 - wt
-                     t3 = newTemp(Ity_V128); // rv
-                     t4 = newTemp(Ity_V128); // wt % 32 == 0
-                     assign(t1,
-                            binop(Iop_Sar32x4,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x2000000020ul),
-                                        mkU64(0x2000000020ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ32x4,
-                                       binop(Iop_ShlN32x4,
-                                             getWReg(wt),
-                                             mkU8(27)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN32x4,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl32x4,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(31)));
-                     putWReg(wd,
-                             binop(Iop_Add32x4,
-                                   mkexpr(t1), mkexpr(t3)));
                      break;
-                  }
 
-               case 0x03: { /* SRAR.D */
-                     DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Sar64x2,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(64ul), mkU64(64ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ64x2,
-                                       binop(Iop_ShlN64x2,
-                                             getWReg(wt),
-                                             mkU8(58)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN64x2,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl64x2,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(63)));
-                     putWReg(wd,
-                             binop(Iop_Add64x2,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
+                  default:
+                     return -1;
+               }
 
-               default:
-                  return -1;
+               break;
             }
 
-            break;
-         }
-
-      case 0x02: { /* SRLR.df */
-            switch (df) {
-               case 0x00: { /* SRLR.B */
-                     DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shr8x16,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub8x16,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x808080808080808ull),
-                                        mkU64(0x808080808080808ull)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ8x16,
-                                       binop(Iop_ShlN8x16,
-                                             getWReg(wt),
-                                             mkU8(5)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN8x16,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl8x16,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(7)));
-                     putWReg(wd,
-                             binop(Iop_Add8x16,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
-
-               case 0x01: { /* SRLR.H */
-                     DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shr16x8,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub16x8,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x10001000100010ul),
-                                        mkU64(0x10001000100010ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ16x8,
-                                       binop(Iop_ShlN16x8,
-                                             getWReg(wt),
-                                             mkU8(12)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN16x8,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl16x8,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(15)));
-                     putWReg(wd,
-                             binop(Iop_Add16x8,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
+            case 0x04: { /* INSERT.df */
+               t5 = newTemp(Ity_I64);
+               UInt hi = 1;
+               ULong mask;
+               IRTemp *src, *dst;
+               assign(t5, mode64 ? getIReg(ws) :
+                      unop(Iop_32Uto64, getIReg(ws)));
 
-               case 0x02: { /* SRLR.W */
-                     DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shr32x4,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x2000000020ul),
-                                        mkU64(0x2000000020ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ32x4,
-                                       binop(Iop_ShlN32x4,
-                                             getWReg(wt),
-                                             mkU8(27)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN32x4,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl32x4,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(31)));
-                     putWReg(wd,
-                             binop(Iop_Add32x4,
-                                   mkexpr(t1), mkexpr(t3)));
-                     break;
-                  }
+               if (df == 0x38) { /* INSERT.D */
+                  if (mode64) {
+                     DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
+
+                     if (n == 0) {
+                        putWReg(wd,
+                                binop(Iop_64HLtoV128,
+                                      unop(Iop_V128HIto64,
+                                           getWReg(wd)),
+                                      mkexpr(t5)));
+                     } else {
+                        putWReg(wd,
+                                binop(Iop_64HLtoV128,
+                                      mkexpr(t5),
+                                      unop(Iop_V128to64,
+                                           getWReg(wd))));
+                     }
 
-               case 0x03: { /* SRLR.D */
-                     DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_Shr64x2,
-                                  getWReg(ws),
-                                  getWReg(wt)));
-                     assign(t2,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(64ul), mkU64(64ul)),
-                                  getWReg(wt)));
-                     assign(t4,
-                            unop(Iop_NotV128,
-                                 binop(Iop_CmpEQ64x2,
-                                       binop(Iop_ShlN64x2,
-                                             getWReg(wt),
-                                             mkU8(58)),
-                                       binop(Iop_64HLtoV128,
-                                             mkU64(0), mkU64(0)))));
-                     assign(t3,
-                            binop(Iop_ShrN64x2,
-                                  binop(Iop_AndV128,
-                                        binop(Iop_Shl64x2,
-                                              getWReg(ws),
-                                              mkexpr(t2)),
-                                        mkexpr(t4)),
-                                  mkU8(63)));
-                     putWReg(wd,
-                             binop(Iop_Add64x2,
-                                   mkexpr(t1), mkexpr(t3)));
                      break;
+                  } else {
+                     return -2;
                   }
+               } else {
+                  t1 = newTemp(Ity_I64);
+                  t2 = newTemp(Ity_I64);
+                  assign(t1, unop(Iop_V128to64, getWReg(wd)));
+                  assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
+               }
 
-               default:
-                  return -1;
-            }
+               switch (df) {
+                  case 0x00: /* INSERT.B */
+                     DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
 
-            break;
-         }
+                     if (n >= 8) {
+                        n -= 8;
+                     } else {
+                        hi = 0;
+                     }
 
-      case 0x04: { /* HADD_S.df */
-            switch (df) {
-               case 0x01: { /* HADD_S.H */
-                     DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add16x8,
-                                  binop(Iop_SarN16x8,
-                                        mkexpr(t1), mkU8(8)),
-                                  binop(Iop_SarN16x8,
-                                        binop(Iop_ShlN16x8,
-                                              mkexpr(t2), mkU8(8)),
-                                        mkU8(8))));
-                     putWReg(wd, mkexpr(t3));
+                     n <<= 3;
+                     mask = 0xFFull;
                      break;
-                  }
 
-               case 0x02: { /* HADD_S.W */
-                     DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add32x4,
-                                  binop(Iop_SarN32x4,
-                                        mkexpr(t1), mkU8(16)),
-                                  binop(Iop_SarN32x4,
-                                        binop(Iop_ShlN32x4,
-                                              mkexpr(t2), mkU8(16)),
-                                        mkU8(16))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                  case 0x20: /* INSERT.H */
+                     DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
 
-               case 0x03: { /* HADD_S.D */
-                     DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add64x2,
-                                  binop(Iop_SarN64x2,
-                                        mkexpr(t1), mkU8(32)),
-                                  binop(Iop_SarN64x2,
-                                        binop(Iop_ShlN64x2,
-                                              mkexpr(t2), mkU8(32)),
-                                        mkU8(32))));
-                     putWReg(wd, mkexpr(t3));
+                     if (n >= 4) {
+                        n -= 4;
+                     } else {
+                        hi = 0;
+                     }
+
+                     n <<= 4;
+                     mask = 0xFFFFull;
                      break;
-                  }
 
-               default:
-                  return -1;
-            }
+                  case 0x30: /* INSERT.W */
+                     DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
 
-            break;
-         }
+                     if (n >= 2) {
+                        n -= 2;
+                     } else {
+                        hi = 0;
+                     }
 
-      case 0x05: { /* HADD_U.df */
-            switch (df) {
-               case 0x01: { /* HADD_U.H */
-                     DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add16x8,
-                                  binop(Iop_ShrN16x8,
-                                        mkexpr(t1), mkU8(8)),
-                                  binop(Iop_ShrN16x8,
-                                        binop(Iop_ShlN16x8,
-                                              mkexpr(t2), mkU8(8)),
-                                        mkU8(8))));
-                     putWReg(wd, mkexpr(t3));
+                     n <<= 5;
+                     mask = 0xFFFFFFFFull;
                      break;
-                  }
 
-               case 0x02: { /* HADD_U.W */
-                     DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
+                  default:
+                     return -1;
+               }
+
+               if (hi) {
+                  t4 = newTemp(Ity_I64);
+                  src = &t2;
+                  dst = &t4;
+                  t3 = t1;
+               } else {
+                  t3 = newTemp(Ity_I64);
+                  src = &t1;
+                  dst = &t3;
+                  t4 = t2;
+               }
+
+               mask <<= n;
+               assign(*dst,
+                      binop(Iop_Or64,
+                            binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
+                            binop(Iop_And64,
+                                  binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
+                                  mkU64(mask))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
+               break;
+            }
+
+            case 0x05: { /* INSVE.df */
+               switch (df) {
+                  case 0x00: { /* INSVE.B */
+                     DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add32x4,
-                                  binop(Iop_ShrN32x4,
-                                        mkexpr(t1), mkU8(16)),
-                                  binop(Iop_ShrN32x4,
-                                        binop(Iop_ShlN32x4,
-                                              mkexpr(t2), mkU8(16)),
-                                        mkU8(16))));
-                     putWReg(wd, mkexpr(t3));
+                     assign(t1, getWReg(wd));
+                     assign(t2, getWReg(ws));
+                     Int i;
+                     IRTemp tmp[16];
+
+                     for (i = 0; i < 16; i++) {
+                        tmp[i] = newTemp(Ity_I8);
+
+                        if (n == i)
+                           assign(tmp[i],
+                                  binop(Iop_GetElem8x16,
+                                        mkexpr(t2), mkU8(0x0)));
+                        else
+                           assign(tmp[i],
+                                  binop(Iop_GetElem8x16,
+                                        mkexpr(t1), mkU8(i)));
+                     }
+
+                     putWReg(wd,
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[15]),
+                                                     mkexpr(tmp[14])),
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[13]),
+                                                     mkexpr(tmp[12]))),
+                                         binop(Iop_16HLto32,
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[11]),
+                                                     mkexpr(tmp[10])),
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[9]),
+                                                     mkexpr(tmp[8])))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[7]),
+                                                     mkexpr(tmp[6])),
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[5]),
+                                                     mkexpr(tmp[4]))),
+                                         binop(Iop_16HLto32,
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[3]),
+                                                     mkexpr(tmp[2])),
+                                               binop(Iop_8HLto16,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0]))))));
                      break;
                   }
 
-               case 0x03: { /* HADD_U.D */
-                     DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
+                  case 0x20: { /* INSVE.H */
+                     DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Add64x2,
-                                  binop(Iop_ShrN64x2,
-                                        mkexpr(t1), mkU8(32)),
-                                  binop(Iop_ShrN64x2,
-                                        binop(Iop_ShlN64x2,
-                                              mkexpr(t2), mkU8(32)),
-                                        mkU8(32))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+                     assign(t1, getWReg(wd));
+                     assign(t2, getWReg(ws));
+                     Int i;
+                     IRTemp tmp[8];
 
-               default:
-                  return -1;
-            }
+                     for (i = 0; i < 8; i++) {
+                        tmp[i] = newTemp(Ity_I16);
 
-            break;
-         }
+                        if (n == i)
+                           assign(tmp[i],
+                                  binop(Iop_GetElem16x8,
+                                        mkexpr(t2), mkU8(0x0)));
+                        else
+                           assign(tmp[i],
+                                  binop(Iop_GetElem16x8,
+                                        mkexpr(t1), mkU8(i)));
+                     }
 
-      case 0x06: { /* HSUB_S.df */
-            switch (df) {
-               case 0x01: { /* HSUB_S.H */
-                     DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub16x8,
-                                  binop(Iop_SarN16x8,
-                                        mkexpr(t1), mkU8(8)),
-                                  binop(Iop_SarN16x8,
-                                        binop(Iop_ShlN16x8,
-                                              mkexpr(t2), mkU8(8)),
-                                        mkU8(8))));
-                     putWReg(wd, mkexpr(t3));
+                     putWReg(wd,
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[7]),
+                                               mkexpr(tmp[6])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[5]),
+                                               mkexpr(tmp[4]))),
+                                   binop(Iop_32HLto64,
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[3]),
+                                               mkexpr(tmp[2])),
+                                         binop(Iop_16HLto32,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0])))));
                      break;
                   }
 
-               case 0x02: { /* HSUB_S.W */
-                     DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+                  case 0x30: { /* INSVE.W */
+                     DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_SarN32x4,
-                                        mkexpr(t1), mkU8(16)),
-                                  binop(Iop_SarN32x4,
-                                        binop(Iop_ShlN32x4,
-                                              mkexpr(t2), mkU8(16)),
-                                        mkU8(16))));
-                     putWReg(wd, mkexpr(t3));
+                     assign(t1, getWReg(wd));
+                     assign(t2, getWReg(ws));
+                     Int i;
+                     IRTemp tmp[4];
+
+                     for (i = 0; i < 4; i++) {
+                        tmp[i] = newTemp(Ity_I32);
+
+                        if (n == i)
+                           assign(tmp[i],
+                                  binop(Iop_GetElem32x4,
+                                        mkexpr(t2), mkU8(0x0)));
+                        else
+                           assign(tmp[i],
+                                  binop(Iop_GetElem32x4,
+                                        mkexpr(t1), mkU8(i)));
+                     }
+
+                     putWReg(wd,
+                             binop(Iop_64HLtoV128,
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[3]),
+                                         mkexpr(tmp[2])),
+                                   binop(Iop_32HLto64,
+                                         mkexpr(tmp[1]),
+                                         mkexpr(tmp[0]))));
                      break;
                   }
 
-               case 0x03: { /* HSUB_S.D */
-                     DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+                  case 0x38: { /* INSVE.D */
+                     DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
                      t1 = newTemp(Ity_V128);
                      t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_SarN64x2,
-                                        mkexpr(t1), mkU8(32)),
-                                  binop(Iop_SarN64x2,
-                                        binop(Iop_ShlN64x2,
-                                              mkexpr(t2), mkU8(32)),
-                                        mkU8(32))));
-                     putWReg(wd, mkexpr(t3));
+                     assign(t1, getWReg(wd));
+                     assign(t2, getWReg(ws));
+                     Int i;
+                     IRTemp tmp[2];
+
+                     for (i = 0; i < 2; i++) {
+                        tmp[i] = newTemp(Ity_I64);
+
+                        if (n == i)
+                           assign(tmp[i],
+                                  binop(Iop_GetElem64x2,
+                                        mkexpr(t2), mkU8(0x0)));
+                        else
+                           assign(tmp[i],
+                                  binop(Iop_GetElem64x2,
+                                        mkexpr(t1), mkU8(i)));
+                     }
+
+                     putWReg(wd,
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(tmp[1]), mkexpr(tmp[0])));
                      break;
                   }
+               }
 
-               default:
-                  return -1;
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
+   }
 
-      case 0x07: { /* HSUB_U.df */
-            switch (df) {
-               case 0x01: { /* HSUB_U.H */
-                     DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub16x8,
-                                  binop(Iop_ShrN16x8,
-                                        mkexpr(t1), mkU8(8)),
-                                  binop(Iop_ShrN16x8,
-                                        binop(Iop_ShlN16x8,
-                                              mkexpr(t2), mkU8(8)),
-                                        mkU8(8))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+   return 0;
+}
+
+static Int msa_VEC(UInt cins, UChar wd, UChar ws)   /* VEC */
+{
+   IRTemp t1, t2, t3;
+   UShort operation;
+   UChar wt;
+
+   vassert((cins & 0x03000000) == 0);
+
+   operation = (cins & 0x03E00000) >> 21;
+   wt = (cins & 0x001F0000) >> 16;
+
+   switch (operation) {
+      case 0x00: { /* AND.V */
+         DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
+         assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-               case 0x02: { /* HSUB_U.W */
-                     DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_ShrN32x4,
-                                        mkexpr(t1), mkU8(16)),
-                                  binop(Iop_ShrN32x4,
-                                        binop(Iop_ShlN32x4,
-                                              mkexpr(t2), mkU8(16)),
-                                        mkU8(16))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x01: { /* OR.V */
+         DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-               case 0x03: { /* HSUB_U.D */
-                     DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_ShrN64x2,
-                                        mkexpr(t1), mkU8(32)),
-                                  binop(Iop_ShrN64x2,
-                                        binop(Iop_ShlN64x2,
-                                              mkexpr(t2), mkU8(32)),
-                                        mkU8(32))));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x02: { /* NOR.V */
+         DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
+         assign(t3,
+                unop(Iop_NotV128,
+                     binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-               default:
-                  return -1;
-            }
+      case 0x03: { /* XOR.V */
+         DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         assign(t2, getWReg(wt));
+         assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
-            break;
-         }
+      case 0x04: { /* BMNZ  (ws AND wt) OR (wd AND NOT wt) */
+         DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1,
+                binop(Iop_AndV128,
+                      getWReg(ws), getWReg(wt)));
+         assign(t2,
+                binop(Iop_AndV128,
+                      getWReg(wd),
+                      unop(Iop_NotV128, getWReg(wt))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
+
+      case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
+         DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1,
+                binop(Iop_AndV128,
+                      getWReg(wd), getWReg(wt)));
+         assign(t2,
+                binop(Iop_AndV128,
+                      getWReg(ws),
+                      unop(Iop_NotV128, getWReg(wt))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
+
+      case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
+         DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         assign(t1,
+                binop(Iop_AndV128,
+                      getWReg(wd), getWReg(wt)));
+         assign(t2,
+                binop(Iop_AndV128,
+                      getWReg(ws),
+                      unop(Iop_NotV128, getWReg(wd))));
+         assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+         putWReg(wd, mkexpr(t3));
+         break;
+      }
 
       default:
          return -1;
@@ -20784,3718 +15082,3285 @@ static Int msa_3R_15(UInt cins, UChar wd, UChar ws) { /* 3R (0x15) */
    return 0;
 }
 
-static Int msa_3R_1A(UInt cins, UChar wd, UChar ws) { /* 3R (0x1A) */
+static Int msa_2R(UInt cins, UChar wd, UChar ws)   /* 2R */
+{
+   IRTemp t1, t2, t3, t4;
+   IRType ty;
    UShort operation;
-   UChar df, wt;
+   UChar df;
 
-   operation = (cins & 0x03C00000) >> 22;
-   df = (cins & 0x00200000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+   vassert((cins & 0x00200000) == 0);
+
+   operation = (cins & 0x03FC0000) >> 18;
+   df = (cins & 0x00030000) >> 16;
+   ty = mode64 ? Ity_I64 : Ity_I32;
 
    switch (operation) {
-      case 0x00: { /* FCAF.df */
-            switch (df) {
-               case 0x00: { /* FCAF.W */
-                     DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCAFW, 2);
-                     putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
-                     break;
-                  }
+      case 0xC0: { /* FILL.df */
+         t1 = newTemp(Ity_I64);
 
-               case 0x01: { /* FCAF.D */
-                     DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCAFD, 2);
-                     putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: /* FILL.B */
+               DIP("FILL.B w%d, r%d", wd, ws);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I16);
+               t4 = newTemp(Ity_I8);
+               assign(t4, mkNarrowTo8(ty, getIReg(ws)));
+               assign(t3,
+                      binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
+               assign(t2,
+                      binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
+               assign(t1,
+                      binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+               break;
 
-               default:
-                  return -1;
-            }
+            case 0x01: /* FILL.H */
+               DIP("FILL.H w%d, r%d", wd, ws);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I16);
+               assign(t3, mkNarrowTo16(ty, getIReg(ws)));
+               assign(t2,
+                      binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
+               assign(t1,
+                      binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+               break;
 
-            break;
+            case 0x02: /* FILL.W */
+               DIP("FILL.W w%d, r%d", wd, ws);
+               t2 = newTemp(Ity_I32);
+               assign(t2, mkNarrowTo32(ty, getIReg(ws)));
+               assign(t1,
+                      binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+               break;
+
+            case 0x03: /* FILL.D */
+               if (mode64) {
+                  DIP("FILL.W w%d, r%d", wd, ws);
+                  t2 = newTemp(Ity_I32);
+                  assign(t1, getIReg(ws));
+               } else {
+                  return -2;
+               }
+
+               break;
+
+            default:
+               return -1;
          }
 
-      case 0x01: { /* FCUN.df */
-            switch (df) {
-               case 0x00: { /* FCUN.W */
-                     DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUNW, 2);
-                     putWReg(wd, binop(Iop_CmpUN32Fx4,
-                                       getWReg(ws),
-                                       getWReg(wt)));
-                     break;
-                  }
+         putWReg(wd,
+                 binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
+         break;
+      }
 
-               case 0x01: { /* FCUN.D */
-                     DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUND, 2);
-                     putWReg(wd, binop(Iop_CmpUN64Fx2,
-                                       getWReg(ws),
-                                       getWReg(wt)));
-                     break;
-                  }
+      case 0xC1: { /* PCNT.df */
+         switch (df) {
+            case 0x00: /* PCNT.B */
+               DIP("PCNT.B w%d, r%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Cnt8x16, getWReg(ws)));
+               break;
 
-               default:
-                  return -1;
-            }
+            case 0x01: /* PCNT.H */
+               DIP("PCNT.H w%d, r%d", wd, ws);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+               assign(t2,
+                      binop(Iop_Add16x8,
+                            binop(Iop_AndV128,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN16x8,
+                                        mkexpr(t1), mkU8(8)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL)))));
+               putWReg(wd, mkexpr(t2));
+               break;
 
-            break;
+            case 0x02: /* PCNT.W */
+               DIP("PCNT.W w%d, r%d", wd, ws);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+               assign(t2,
+                      binop(Iop_Add32x4,
+                            binop(Iop_AndV128,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN32x4,
+                                        mkexpr(t1), mkU8(8)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL)))));
+               assign(t3,
+                      binop(Iop_Add32x4,
+                            binop(Iop_AndV128,
+                                  mkexpr(t2),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0000FFFF0000FFFFULL),
+                                        mkU64(0x0000FFFF0000FFFFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN32x4,
+                                        mkexpr(t2), mkU8(16)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0000FFFF0000FFFFULL),
+                                        mkU64(0x0000FFFF0000FFFFULL)))));
+               putWReg(wd, mkexpr(t3));
+               break;
+
+            case 0x03: /* PCNT.D */
+               DIP("PCNT.D w%d, r%d", wd, ws);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_V128);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);;
+               assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+               assign(t2,
+                      binop(Iop_Add64x2,
+                            binop(Iop_AndV128,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN64x2,
+                                        mkexpr(t1), mkU8(8)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00FF00FF00FF00FFULL),
+                                        mkU64(0x00FF00FF00FF00FFULL)))));
+               assign(t3,
+                      binop(Iop_Add64x2,
+                            binop(Iop_AndV128,
+                                  mkexpr(t2),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0000FFFF0000FFFFULL),
+                                        mkU64(0x0000FFFF0000FFFFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN64x2,
+                                        mkexpr(t2), mkU8(16)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0000FFFF0000FFFFULL),
+                                        mkU64(0x0000FFFF0000FFFFULL)))));
+               assign(t4,
+                      binop(Iop_Add64x2,
+                            binop(Iop_AndV128,
+                                  mkexpr(t3),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00000000FFFFFFFFULL),
+                                        mkU64(0x00000000FFFFFFFFULL))),
+                            binop(Iop_AndV128,
+                                  binop(Iop_ShrN64x2,
+                                        mkexpr(t3), mkU8(32)),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x00000000FFFFFFFFULL),
+                                        mkU64(0x00000000FFFFFFFFULL)))));
+               putWReg(wd, mkexpr(t4));
+               break;
+
+            default:
+               return -1;
          }
 
-      case 0x02: { /* FCEQ.df */
-            switch (df) {
-               case 0x00: { /* FCEQ.W */
-                     DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCEQW, 2);
-                     putWReg(wd, binop(Iop_CmpEQ32Fx4,
-                                       getWReg(ws),
-                                       getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FCEQ.D */
-                     DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCEQD, 2);
-                     putWReg(wd, binop(Iop_CmpEQ64Fx2,
-                                       getWReg(ws),
-                                       getWReg(wt)));
-                     break;
-                  }
+      case 0xC2: { /* NLOC.df */
+         switch (df) {
+            case 0x00: /* NLOC.B */
+               DIP("NLOC.B w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Cls8x16, getWReg(ws)));
+               break;
 
-               default:
-                  return -1;
-            }
+            case 0x01: /* NLOC.H */
+               DIP("NLOC.H w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Cls16x8, getWReg(ws)));
+               break;
 
-            break;
+            case 0x02: /* NLOC.W */
+               DIP("NLOC.W w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Cls32x4, getWReg(ws)));
+               break;
+
+            case 0x03: /* NLOC.D */
+               DIP("NLOC.D w%d, w%d", wd, ws);
+               t1 = newTemp(Ity_V128);
+               assign(t1, unop(Iop_NotV128, getWReg(ws)));
+               putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
+               break;
+
+            default:
+               return -1;
          }
 
-      case 0x03: { /* FCUEQ.df */
-            switch (df) {
-               case 0x00: { /* FCUEQ.W */
-                     DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUEQW, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpEQ32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FCUEQ.D */
-                     DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUEQD, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpEQ64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0xC3: { /* NLZC.df */
+         switch (df) {
+            case 0x00: /* NLZC.B */
+               DIP("NLZC.W w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Clz8x16, getWReg(ws)));
+               break;
 
-               default:
-                  return -1;
+            case 0x01: /* NLZC.H */
+               DIP("NLZC.H w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Clz16x8, getWReg(ws)));
+               break;
+
+            case 0x02: /* NLZC.W */
+               DIP("NLZC.W w%d, w%d", wd, ws);
+               putWReg(wd,
+                       unop(Iop_Clz32x4, getWReg(ws)));
+               break;
+
+            case 0x03: {/* NLZC.D */
+               putWReg(wd,
+                       unop(Iop_Clz64x2, getWReg(ws)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x04: { /* FCLT.df */
-            switch (df) {
-               case 0x00: { /* FCLT.W */
-                     DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCLTW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLT32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FCLT.D */
-                     DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCLTD, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLT64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static Int msa_2RF(UInt cins, UChar wd, UChar ws)   /* 2RF */
+{
+   IRTemp t1, t2, t3, t4, t5;
+   UShort operation;
+   UChar df, wt;
 
-               default:
-                  return -1;
-            }
+   operation = (cins & 0x03FE0000) >> 17;
+   df = (cins & 0x00010000) >> 16;
+   wt = (cins & 0x001F0000) >> 16;
 
-            break;
-         }
+   switch (operation) {
 
-      case 0x05: { /* FCULT.df */
-            switch (df) {
-               case 0x00: { /* FCULT.W */
-                     DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCULTW, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLT32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x190: { /* FCLASS.df */
+         IRTemp t0 = newTemp(Ity_V128);
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         t4 = newTemp(Ity_V128);
+         t5 = newTemp(Ity_V128);
 
-               case 0x01: { /* FCULT.D */
-                     DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCULTD, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLT64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         switch (df) {
+            case 0x00: { /* FCLASS.W */
+               DIP("FCLASS.W w%d, w%d", wd, ws);
+               assign(t0,
+                      binop(Iop_CmpEQ32x4,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x7F8000007F800000ull),
+                                        mkU64(0x7F8000007F800000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0ull), mkU64(0ull))));
+               assign(t1,
+                      binop(Iop_CmpEQ32x4,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x7F8000007F800000ull),
+                                        mkU64(0x7F8000007F800000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7F8000007F800000ull),
+                                  mkU64(0x7F8000007F800000ull))));
+               assign(t2,
+                      binop(Iop_SarN32x4,
+                            getWReg(ws), mkU8(31)));
+               assign(t3,
+                      binop(Iop_CmpEQ32x4,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0040000000400000ull),
+                                        mkU64(0x0040000000400000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x0040000000400000ull),
+                                  mkU64(0x0040000000400000ull))));
+               assign(t4,
+                      binop(Iop_CmpEQ32x4,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x007FFFFF007FFFFFULL),
+                                        mkU64(0x007FFFFF007FFFFFULL))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0ull), mkU64(0ull))));
+               assign(t5,
+                      binop(Iop_Shl32x4,
+                            binop(Iop_OrV128,
+                                  binop(Iop_AndV128,
+                                        mkexpr(t1),
+                                        binop(Iop_AndV128,
+                                              mkexpr(t4),
+                                              binop(Iop_64HLtoV128,
+                                                    mkU64(0x100000001ull),
+                                                    mkU64(0x100000001ull)))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              mkexpr(t0),
+                                              binop(Iop_OrV128,
+                                                    binop(Iop_AndV128,
+                                                          mkexpr(t4),
+                                                          binop(Iop_64HLtoV128,
+                                                                mkU64(0x800000008ull),
+                                                                mkU64(0x800000008ull))),
+                                                    binop(Iop_AndV128,
+                                                          unop(Iop_NotV128,
+                                                                mkexpr(t4)),
+                                                          binop(Iop_64HLtoV128,
+                                                                mkU64(0x400000004ull),
+                                                                mkU64(0x400000004ull))))),
+                                        binop(Iop_AndV128,
+                                              unop(Iop_NotV128,
+                                                   mkexpr(t1)),
+                                              binop(Iop_AndV128,
+                                                    unop(Iop_NotV128,
+                                                          mkexpr(t0)),
+                                                    binop(Iop_64HLtoV128,
+                                                          mkU64(0x200000002ull),
+                                                          mkU64(0x200000002ull)))))),
+                            binop(Iop_OrV128,
+                                  binop(Iop_AndV128,
+                                        mkexpr(t2),
+                                        binop(Iop_64HLtoV128,
+                                              mkU64(0x200000002ull),
+                                              mkU64(0x200000002ull))),
+                                  binop(Iop_AndV128,
+                                        unop(Iop_NotV128,
+                                             mkexpr(t2)),
+                                        binop(Iop_64HLtoV128,
+                                              mkU64(0x600000006ull),
+                                              mkU64(0x600000006ull))))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t5),
+                             binop(Iop_AndV128,
+                                   binop(Iop_CmpEQ32x4,
+                                         mkexpr(t5),
+                                         binop(Iop_64HLtoV128,
+                                               mkU64(0ull),
+                                               mkU64(0ull))),
+                                   binop(Iop_OrV128,
+                                         binop(Iop_AndV128,
+                                               mkexpr(t3),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(0x100000001ull),
+                                                     mkU64(0x100000001ull))),
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128, mkexpr(t3)),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(0x200000002ull),
+                                                     mkU64(0x200000002ull)))))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FCLASS.D */
+               DIP("FCLASS.D w%d, w%d", wd, ws);
+               assign(t0,
+                      binop(Iop_CmpEQ64x2,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x7FF0000000000000ull),
+                                        mkU64(0x7FF0000000000000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0ull), mkU64(0ull))));
+               assign(t1,
+                      binop(Iop_CmpEQ64x2,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x7FF0000000000000ull),
+                                        mkU64(0x7FF0000000000000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x7FF0000000000000ull),
+                                  mkU64(0x7FF0000000000000ull))));
+               assign(t2,
+                      binop(Iop_SarN64x2,
+                            getWReg(ws), mkU8(63)));
+               assign(t3,
+                      binop(Iop_CmpEQ64x2,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0008000000000000ull),
+                                        mkU64(0x0008000000000000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x0008000000000000ull),
+                                  mkU64(0x0008000000000000ull))));
+               assign(t4,
+                      binop(Iop_CmpEQ64x2,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x000FFFFFFFFFFFFFULL),
+                                        mkU64(0x000FFFFFFFFFFFFFULL))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0ull), mkU64(0ull))));
+               assign(t5,
+                      binop(Iop_Shl64x2,
+                            binop(Iop_OrV128,
+                                  binop(Iop_AndV128,
+                                        mkexpr(t1),
+                                        binop(Iop_AndV128,
+                                              mkexpr(t4),
+                                              binop(Iop_64HLtoV128,
+                                                    mkU64(1ull),
+                                                    mkU64(1ull)))),
+                                  binop(Iop_OrV128,
+                                        binop(Iop_AndV128,
+                                              mkexpr(t0),
+                                              binop(Iop_OrV128,
+                                                    binop(Iop_AndV128,
+                                                          mkexpr(t4),
+                                                          binop(Iop_64HLtoV128,
+                                                                mkU64(8ull),
+                                                                mkU64(8ull))),
+                                                    binop(Iop_AndV128,
+                                                          unop(Iop_NotV128,
+                                                                mkexpr(t4)),
+                                                          binop(Iop_64HLtoV128,
+                                                                mkU64(4ull),
+                                                                mkU64(4ull))))),
+                                        binop(Iop_AndV128,
+                                              unop(Iop_NotV128,
+                                                   mkexpr(t1)),
+                                              binop(Iop_AndV128,
+                                                    unop(Iop_NotV128,
+                                                          mkexpr(t0)),
+                                                    binop(Iop_64HLtoV128,
+                                                          mkU64(2ull),
+                                                          mkU64(2ull)))))),
+                            binop(Iop_OrV128,
+                                  binop(Iop_AndV128,
+                                        mkexpr(t2),
+                                        binop(Iop_64HLtoV128,
+                                              mkU64(2ull),
+                                              mkU64(2ull))),
+                                  binop(Iop_AndV128,
+                                        unop(Iop_NotV128,
+                                             mkexpr(t2)),
+                                        binop(Iop_64HLtoV128,
+                                              mkU64(6ull),
+                                              mkU64(6ull))))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             mkexpr(t5),
+                             binop(Iop_AndV128,
+                                   binop(Iop_CmpEQ64x2,
+                                         mkexpr(t5),
+                                         binop(Iop_64HLtoV128,
+                                               mkU64(0ull),
+                                               mkU64(0ull))),
+                                   binop(Iop_OrV128,
+                                         binop(Iop_AndV128,
+                                               mkexpr(t3),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(1ull),
+                                                     mkU64(1ull))),
+                                         binop(Iop_AndV128,
+                                               unop(Iop_NotV128,
+                                                    mkexpr(t3)),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(2ull),
+                                                     mkU64(2ull)))))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x06: { /* FCLE.df */
-            switch (df) {
-               case 0x00: { /* FCLE.W */
-                     DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCLEW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLE32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FCLE.D */
-                     DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCLED, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLE64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x191: { /* FTRUNC_S.df */
+         switch (df) {
+            case 0x00: { /* FTRUNC_S.W */
+               DIP("FTRUNC_S.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTRUNCSW, 1);
+               putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FTRUNC_S.D */
+               DIP("FTRUNC_S.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTRUNCSD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               assign(t3,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128,
+                                 binop(Iop_CmpUN64Fx2,
+                                       getWReg(ws),
+                                       getWReg(ws))),
+                            binop(Iop_Max64Fx2,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0xC3E0000000000000),
+                                        mkU64(0xC3E0000000000000)))));
+               assign(t1,
+                      binop(Iop_F64toI64S, mkU32(0x3),
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128to64, mkexpr(t3)))));
+               assign(t2,
+                      binop(Iop_F64toI64S, mkU32(0x3),
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128HIto64, mkexpr(t3)))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x07: { /* FCULE.df */
-            switch (df) {
-               case 0x00: { /* FCULE.W */
-                     DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCULEW, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLE32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FCULE.D */
-                     DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCULED, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLE64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x192: { /* FTRUNC_U.df */
+         switch (df) {
+            case 0x00: {  /* FTRUNC_U.W */
+               DIP("FTRUNC_U.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTRUNCUW, 1);
+               putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FTRUNC_U.D */
+               DIP("FTRUNC_U.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTRUNCUD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               assign(t1,
+                      binop(Iop_F64toI64U,
+                            mkU32(0x3),
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128to64,
+                                      getWReg(ws)))));
+               assign(t2,
+                      binop(Iop_F64toI64U,
+                            mkU32(0x3),
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128HIto64,
+                                      getWReg(ws)))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x08: { /* FSAF.df */
-            switch (df) {
-               case 0x00: { /* FSAF.W */
-                     DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSAFW, 2);
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkU64(0ul), mkU64(0ul)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSAF.D */
-                     DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSAFD, 2);
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkU64(0ul), mkU64(0ul)));
-                     break;
-                  }
+      case 0x193: { /* FSQRT.df */
+         switch (df) {
+            case 0x00: { /* FSQRT.W */
+               DIP("FSQRT.W w%d, w%d", wd, ws);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               calculateMSACSR(ws, wd, FSQRTW, 1);
+               putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FSQRT.D */
+               DIP("FSQRT.D w%d, w%d", wd, ws);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               calculateMSACSR(ws, wd, FSQRTD, 1);
+               putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x09: { /* FSUN.df */
-            switch (df) {
-               case 0x00: { /* FSUN.W */
-                     DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUNW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpUN32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSUN.D */
-                     DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUND, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpUN64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x194: { /* FRSQRT.df */
+         switch (df) {
+            case 0x00: { /* FRSQRT.W */
+               DIP("FRSQRT.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FRSQRTW, 1);
+               putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FRSQRT.D */
+               DIP("FRSQRT.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FRSQRTD, 1);
+               putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x0A: { /* FSEQ.df */
-            switch (df) {
-               case 0x00: { /* FSEQ.W */
-                     DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSEQW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpEQ32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSEQ.D */
-                     DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSEQD, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpEQ64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x195: { /* FRCP.df */
+         switch (df) { /* FRCP.W */
+            case 0x00: {
+               DIP("FRCP.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FRCPW, 1);
+               putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FRCP.D */
+               DIP("FRCP.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FRCPD, 1);
+               putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x0B: { /* FSUEQ.df */
-            switch (df) {
-               case 0x00: { /* FSUEQ.W */
-                     DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUEQW, 2);
-                     putWReg(wd,
+         break;
+      }
+
+      case 0x196: { /* FRINT.df */
+         t1 = newTemp(Ity_V128);
+         t2 = newTemp(Ity_V128);
+         t3 = newTemp(Ity_V128);
+         t4 = newTemp(Ity_V128);
+         IRExpr *rm = get_IR_roundingmode_MSA();
+         assign(t1, getWReg(ws));
+
+         switch (df) {
+            case 0x00: { /* FRINT.W */
+               DIP("FRINT.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FRINTW, 1);
+               assign(t2,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpLT32Fx4,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0xCF000000CF000000ull),
+                                        mkU64(0xCF000000CF000000ull))),
+                            binop(Iop_CmpLT32Fx4,
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x4F0000004F000000ull),
+                                        mkU64(0x4F0000004F000000ull)),
+                                  mkexpr(t1))));
+               assign(t3,
+                      binop(Iop_CmpEQ32x4,
+                            binop(Iop_AndV128,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0040000000400000ull),
+                                        mkU64(0x0040000000400000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x0040000000400000ull),
+                                  mkU64(0x0040000000400000ull))));
+               assign(t4,
+                      binop(Iop_CmpUN32Fx4,
+                            mkexpr(t1), mkexpr(t1)));
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_I32);
+                  assign(tmp[i],
+                         unop(Iop_ReinterpF32asI32,
+                              binop(Iop_RoundF32toInt, rm,
+                                    unop(Iop_ReinterpI32asF32,
+                                         binop(Iop_GetElem32x4,
+                                               mkexpr(t1), mkU8(i))))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_OrV128,
                              binop(Iop_OrV128,
-                                   binop(Iop_CmpEQ32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+                                   binop(Iop_AndV128,
+                                         binop(Iop_OrV128,
+                                               mkexpr(t2),
+                                               binop(Iop_AndV128,
+                                                     mkexpr(t4),
+                                                     unop(Iop_NotV128,
+                                                           mkexpr(t3)))),
+                                         mkexpr(t1)),
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               mkexpr(t4),
+                                               mkexpr(t3)),
+                                         binop(Iop_64HLtoV128,
+                                               mkU64(0x7FBFFFFF7FBFFFFF),
+                                               mkU64(0x7FBFFFFF7FBFFFFF)))),
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128,
+                                        binop(Iop_OrV128,
+                                              mkexpr(t2),
+                                              mkexpr(t4))),
+                                   binop(Iop_OrV128,
+                                         binop(Iop_64HLtoV128,
+                                               binop(Iop_32HLto64,
+                                                     mkexpr(tmp[3]),
+                                                     mkexpr(tmp[2])),
+                                               binop(Iop_32HLto64,
+                                                     mkexpr(tmp[1]),
+                                                     mkexpr(tmp[0]))),
+                                         binop(Iop_AndV128,
+                                               mkexpr(t1),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(0x8000000080000000ull),
+                                                     mkU64(0x8000000080000000ull)))
+                                        ))));
+               break;
+            }
 
-               case 0x01: { /* FSUEQ.D */
-                     DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUEQD, 2);
-                     putWReg(wd,
+            case 0x01: { /* FRINT.D */
+               DIP("FRINT.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FRINTD, 1);
+               assign(t2,
+                      binop(Iop_OrV128,
+                            binop(Iop_CmpLT64Fx2,
+                                  mkexpr(t1),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0xC3E0000000000000ull),
+                                        mkU64(0xC3E0000000000000ull))),
+                            binop(Iop_CmpLT64Fx2,
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x43E0000000000000ull),
+                                        mkU64(0x43E0000000000000ull)),
+                                  mkexpr(t1))));
+               assign(t3,
+                      binop(Iop_CmpEQ64x2,
+                            binop(Iop_AndV128,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0x0008000000000000ull),
+                                        mkU64(0x0008000000000000ull))),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x0008000000000000ull),
+                                  mkU64(0x0008000000000000ull))));
+               assign(t4,
+                      binop(Iop_CmpUN64Fx2,
+                            mkexpr(t1), mkexpr(t1)));
+               IRTemp tmp[2];
+               Int i;
+
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_I64);
+                  assign(tmp[i],
+                         unop(Iop_ReinterpF64asI64,
+                              binop(Iop_RoundF64toInt, rm,
+                                    unop(Iop_ReinterpI64asF64,
+                                         binop(Iop_GetElem64x2,
+                                               mkexpr(t1), mkU8(i))))));
+               }
+
+               putWReg(wd,
+                       binop(Iop_OrV128,
                              binop(Iop_OrV128,
-                                   binop(Iop_CmpEQ64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+                                   binop(Iop_AndV128,
+                                         binop(Iop_OrV128,
+                                               mkexpr(t2),
+                                               binop(Iop_AndV128,
+                                                     mkexpr(t4),
+                                                     unop(Iop_NotV128,
+                                                           mkexpr(t3)))),
+                                         mkexpr(t1)),
+                                   binop(Iop_AndV128,
+                                         binop(Iop_AndV128,
+                                               mkexpr(t4),
+                                               mkexpr(t3)),
+                                         binop(Iop_64HLtoV128,
+                                               mkU64(0x7FF7FFFFFFFFFFFF),
+                                               mkU64(0x7FF7FFFFFFFFFFFF)))),
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128,
+                                        binop(Iop_OrV128,
+                                              mkexpr(t2),
+                                              mkexpr(t4))),
+                                   binop(Iop_OrV128,
+                                         binop(Iop_64HLtoV128,
+                                               mkexpr(tmp[1]),
+                                               mkexpr(tmp[0])),
+                                         binop(Iop_AndV128,
+                                               mkexpr(t1),
+                                               binop(Iop_64HLtoV128,
+                                                     mkU64(0x8000000000000000ull),
+                                                     mkU64(0x8000000000000000ull))
+                                              )))));
+               break;
+            }
 
-               default:
-                  return -1;
+            default:
+               return -1;
+         }
+
+         break;
+      }
+
+      case 0x197: { /* FLOG2.df */
+
+         switch (df) {
+            case 0x00: { /* FLOG2.W */
+               DIP("FLOG2.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FLOG2W, 1);
+               putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
+               break;
             }
 
-            break;
+            case 0x01: { /* FLOG2.D */
+               DIP("FLOG2.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FLOG2D, 1);
+               putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x0C: { /* FSLT.df */
-            switch (df) {
-               case 0x00: { /* FSLT.W */
-                     DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSLTW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLT32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSLT.D */
-                     DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSLTD, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLT64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x198: { /* FEXUPL.df */
+         switch (df) {
+            case 0x00: { /* FEXUPL.W */
+               DIP("FEXUPL.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FEXUPLW, 1);
+               putWReg(wd,
+                       unop(Iop_F16toF32x4,
+                            unop(Iop_V128HIto64,
+                                 getWReg(ws))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FEXUPL.D */
+               DIP("FEXUPL.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FEXUPLD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               assign(t1,
+                      unop(Iop_ReinterpF64asI64,
+                           unop(Iop_F32toF64,
+                                unop(Iop_ReinterpI32asF32,
+                                     unop(Iop_64to32,
+                                          unop(Iop_V128HIto64,
+                                               getWReg(ws)))))));
+               assign(t2,
+                      unop(Iop_ReinterpF64asI64,
+                           unop(Iop_F32toF64,
+                                unop(Iop_ReinterpI32asF32,
+                                     unop(Iop_64HIto32,
+                                          unop(Iop_V128HIto64,
+                                               getWReg(ws)))))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x0D: { /* FSULT.df */
-            switch (df) {
-               case 0x00: { /* FSULT.W */
-                     DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSULTW, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLT32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSULT.D */
-                     DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSULTD, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLT64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x199: { /* FEXUPR.df */
+         switch (df) {
+            case 0x00: { /* FEXUPR.W */
+               DIP("FEXUPR.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FEXUPRW, 1);
+               putWReg(wd,
+                       unop(Iop_F16toF32x4,
+                            unop(Iop_V128to64,
+                                 getWReg(ws))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FEXUPR.D */
+               DIP("FEXUPR.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FEXUPRD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               assign(t1,
+                      unop(Iop_ReinterpF64asI64,
+                           unop(Iop_F32toF64,
+                                unop(Iop_ReinterpI32asF32,
+                                     unop(Iop_64to32,
+                                          unop(Iop_V128to64,
+                                               getWReg(ws)))))));
+               assign(t2,
+                      unop(Iop_ReinterpF64asI64,
+                           unop(Iop_F32toF64,
+                                unop(Iop_ReinterpI32asF32,
+                                     unop(Iop_64HIto32,
+                                          unop(Iop_V128to64,
+                                               getWReg(ws)))))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x0E: { /* FSLE.df */
-            switch (df) {
-               case 0x00: { /* FSLE.W */
-                     DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSLEW, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLE32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSLE.D */
-                     DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSLED, 2);
-                     putWReg(wd,
-                             binop(Iop_CmpLE64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x19A: { /* FFQL.df */
+         switch (df) {
+            case 0x00: { /* FFQL.W */
+               DIP("FFQL.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFQLW, 1);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_I64);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveHI16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(1)))),
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(0))))));
+               assign(t3,
+                      binop(Iop_32HLto64,
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(3)))),
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(2))))));
+               putWReg(wd,
+                       triop(Iop_Div32Fx4, rm,
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_64HLtoV128,
+                                   mkU64(0x4700000047000000),
+                                   mkU64(0x4700000047000000))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FFQL.D */
+               DIP("FFQL.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFQLD, 1);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_I64);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveHI32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64StoF64, rm,
+                                 unop(Iop_V128to64,
+                                      mkexpr(t1)))));
+               assign(t3,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64StoF64, rm,
+                                 unop(Iop_V128HIto64,
+                                      mkexpr(t1)))));
+               putWReg(wd,
+                       triop(Iop_Div64Fx2, rm,
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_64HLtoV128,
+                                   mkU64(0x41E0000000000000),
+                                   mkU64(0x41E0000000000000))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x0F: { /* FSULE.df */
-            switch (df) {
-               case 0x00: { /* FSULE.W */
-                     DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSULEW, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLE32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSULE.D */
-                     DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSULED, 2);
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_CmpLE64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt)),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x19B: { /* FFQR.df */
+         switch (df) {
+            case 0x00: { /* FFQR.W */
+               DIP("FFQR.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFQRW, 1);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_I64);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_SarN32x4,
+                            binop(Iop_InterleaveLO16x8,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(16)));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(1)))),
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(0))))));
+               assign(t3,
+                      binop(Iop_32HLto64,
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(3)))),
+                            unop(Iop_ReinterpF32asI32,
+                                 binop(Iop_I32StoF32, rm,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t1),
+                                             mkU8(2))))));
+               putWReg(wd,
+                       triop(Iop_Div32Fx4, rm,
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_64HLtoV128,
+                                   mkU64(0x4700000047000000),
+                                   mkU64(0x4700000047000000))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: { /* FFQR.D */
+               DIP("FFQR.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFQRD, 1);
+               t1 = newTemp(Ity_V128);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_I64);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_SarN64x2,
+                            binop(Iop_InterleaveLO32x4,
+                                  getWReg(ws),
+                                  getWReg(ws)),
+                            mkU8(32)));
+               assign(t2,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64StoF64, rm,
+                                 unop(Iop_V128to64,
+                                      mkexpr(t1)))));
+               assign(t3,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64StoF64, rm,
+                                 unop(Iop_V128HIto64,
+                                      mkexpr(t1)))));
+               putWReg(wd,
+                       triop(Iop_Div64Fx2, rm,
+                             binop(Iop_64HLtoV128,
+                                   mkexpr(t3), mkexpr(t2)),
+                             binop(Iop_64HLtoV128,
+                                   mkU64(0x41E0000000000000),
+                                   mkU64(0x41E0000000000000))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
 
-   return 0;
-}
+      case 0x19C: { /* FTINT_S.df */
+         switch (df) { /* FTINT_S.W */
+            case 0x00: {
+               DIP("FTINT_S.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTINT_SW, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_I32);
+               assign(t3,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128,
+                                 binop(Iop_CmpUN32Fx4,
+                                       getWReg(ws),
+                                       getWReg(ws))),
+                            binop(Iop_Max32Fx4,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0xCF000000CF000000),
+                                        mkU64(0xCF000000CF000000)))));
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_32HLto64,
+                            binop(Iop_F32toI32S, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t3), mkU8(1)))),
+                            binop(Iop_F32toI32S, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t3), mkU8(0))))));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            binop(Iop_F32toI32S, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t3), mkU8(3)))),
+                            binop(Iop_F32toI32S, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             mkexpr(t3), mkU8(2))))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
+            }
 
-static Int msa_3R_1B(UInt cins, UChar wd, UChar ws) { /* 3R (0x1B) */
-   IRTemp t1, t2, t3, t4;
-   UShort operation;
-   UChar df, wt;
+            case 0x01: {  /* FTINT_S.D */
+               DIP("FTINT_S.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTINT_SD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               assign(t3,
+                      binop(Iop_AndV128,
+                            unop(Iop_NotV128,
+                                 binop(Iop_CmpUN64Fx2,
+                                       getWReg(ws),
+                                       getWReg(ws))),
+                            binop(Iop_Max64Fx2,
+                                  getWReg(ws),
+                                  binop(Iop_64HLtoV128,
+                                        mkU64(0xC3E0000000000000),
+                                        mkU64(0xC3E0000000000000)))));
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_F64toI64S, rm,
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128to64, mkexpr(t3)))));
+               assign(t2,
+                      binop(Iop_F64toI64S, rm,
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128HIto64, mkexpr(t3)))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
+            }
 
-   operation = (cins & 0x03C00000) >> 22;
-   df = (cins & 0x00200000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+            default:
+               return -1;
+         }
 
-   switch (operation) {
-      case 0x00: { /* FADD.df */
-            switch (df) {
-               case 0x00: { /* FADD.W */
-                     DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FADDW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Add32Fx4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FADD.D */
-                     DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FADDD, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Add64Fx2, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x19D: {/* FTINT_U.df */
+         switch (df) { /* FTINT_U.W */
+            case 0x00: {
+               DIP("FTINT_U.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTINT_UW, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               t3 = newTemp(Ity_V128);
+               t4 = newTemp(Ity_V128);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_32HLto64,
+                            binop(Iop_F32toI32U, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             getWReg(ws), mkU8(1)))),
+                            binop(Iop_F32toI32U, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             getWReg(ws), mkU8(0))))));
+               assign(t2,
+                      binop(Iop_32HLto64,
+                            binop(Iop_F32toI32U, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             getWReg(ws), mkU8(3)))),
+                            binop(Iop_F32toI32U, rm,
+                                  unop(Iop_ReinterpI32asF32,
+                                       binop(Iop_GetElem32x4,
+                                             getWReg(ws), mkU8(2))))));
+               assign(t3,
+                      unop(Iop_NotV128,
+                           binop(Iop_SarN32x4,
+                                 getWReg(ws),
+                                 mkU8(31))));
+               assign(t4,
+                      binop(Iop_CmpLT32Fx4,
+                            getWReg(ws),
+                            binop(Iop_64HLtoV128,
+                                  mkU64(0x4EFFFFFF4EFFFFFF),
+                                  mkU64(0x4EFFFFFF4EFFFFFF))));
+               putWReg(wd,
+                       binop(Iop_OrV128,
+                             binop(Iop_AndV128,
+                                   mkexpr(t4),
+                                   binop(Iop_AndV128,
+                                         binop(Iop_64HLtoV128,
+                                               mkexpr(t2),
+                                               mkexpr(t1)),
+                                         mkexpr(t3))),
+                             binop(Iop_AndV128,
+                                   unop(Iop_NotV128, mkexpr(t4)),
+                                   unop(Iop_F32toI32Ux4_RZ,
+                                        getWReg(ws)))));
+               break;
+            }
 
-               default:
-                  return -1;
+            case 0x01: {  /* FTINT_U.D */
+               DIP("FTINT_U.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wd, FTINT_UD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1,
+                      binop(Iop_F64toI64U, rm,
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128to64,
+                                      getWReg(ws)))));
+               assign(t2,
+                      binop(Iop_F64toI64U, rm,
+                            unop(Iop_ReinterpI64asF64,
+                                 unop(Iop_V128HIto64,
+                                      getWReg(ws)))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x01: { /* FSUB.df */
-            switch (df) {
-               case 0x00: { /* FSUB.W */
-                     DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUBW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Sub32Fx4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FSUB.D */
-                     DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUBD, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Sub64Fx2, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x19E: { /* FFINT_S.df */
+         t1 = newTemp(Ity_V128);
+         assign(t1, getWReg(ws));
+         IRExpr *rm = get_IR_roundingmode_MSA();
 
-               default:
-                  return -1;
-            }
+         switch (df) {
+            case 0x00: { /* FFINT_S.W */
+               DIP("FFINT_S.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFINTSW, 1);
+               IRTemp tmp[4];
+               Int i;
+
+               for (i = 0; i < 4; i++) {
+                  tmp[i] = newTemp(Ity_F32);
+                  assign(tmp[i],
+                         binop(Iop_I32StoF32, rm,
+                               binop(Iop_GetElem32x4,
+                                     mkexpr(t1), mkU8(i))));
+               }
 
-            break;
-         }
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[3])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[2]))),
+                             binop(Iop_32HLto64,
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[1])),
+                                   unop(Iop_ReinterpF32asI32,
+                                        mkexpr(tmp[0])))));
+               break;
+            }
 
-      case 0x02: { /* FMUL.df */
-            switch (df) {
-               case 0x00: { /* FMUL.W */
-                     DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMULW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Mul32Fx4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+            case 0x01: { /* FFINT_S.D */
+               DIP("FFINT_S.D w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFINTSD, 1);
+               IRTemp tmp[2];
+               Int i;
 
-               case 0x01: { /* FMUL.D */
-                     DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMULW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Mul64Fx2, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+               for (i = 0; i < 2; i++) {
+                  tmp[i] = newTemp(Ity_F64);
+                  assign(tmp[i],
+                         binop(Iop_I64StoF64, rm,
+                               binop(Iop_GetElem64x2,
+                                     mkexpr(t1), mkU8(i))));
+               }
 
-               default:
-                  return -1;
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[1])),
+                             unop(Iop_ReinterpF64asI64,
+                                  mkexpr(tmp[0]))));
+               break;
             }
 
-            break;
+            default:
+               return -1;
          }
 
-      case 0x03: { /* FDIV.df */
-            switch (df) {
-               case 0x00: { /* FDIV.W */
-                     DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FDIVW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Div32Fx4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* FDIV.D */
-                     DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FDIVD, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Div64Fx2, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x19F: { /* FFINT_U.df */
+         IRExpr *rm = get_IR_roundingmode_MSA();
 
-               default:
-                  return -1;
+         switch (df) {
+            case 0x00: { /* FFINT_U.W */
+               DIP("FFINT_U.W w%d, w%d", wd, ws);
+               calculateMSACSR(ws, wt, FFINT_UW, 1);
+               putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
+               break;
             }
 
-            break;
+            case 0x01: { /* FFINT_U.D */
+               DIP("FFINT_U.D w%d, w%d",
+                   wd, ws);
+               calculateMSACSR(ws, wt,
+                               FFINT_UD, 1);
+               t1 = newTemp(Ity_I64);
+               t2 = newTemp(Ity_I64);
+               assign(t1,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64UtoF64, rm,
+                                 unop(Iop_V128to64,
+                                      getWReg(ws)))));
+               assign(t2,
+                      unop(Iop_ReinterpF64asI64,
+                           binop(Iop_I64UtoF64, rm,
+                                 unop(Iop_V128HIto64,
+                                      getWReg(ws)))));
+               putWReg(wd,
+                       binop(Iop_64HLtoV128,
+                             mkexpr(t2), mkexpr(t1)));
+               break;
+            }
+
+            default:
+               return -1;
          }
 
-      case 0x04: { /* FMADD.df */
-            switch (df) {
-               case 0x00: { /* FMADD.W */
-                     DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMADDW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     IRTemp tmp[4];
-                     Int i;
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_F32);
-                        assign(tmp[i],
-                               qop(Iop_MAddF32, rm,
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(ws),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(wt),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(wd),
-                                              mkU8(i)))));
-                     }
+      default:
+         return -1;
+   }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[3])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[2]))),
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[1])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[0])))));
-                     break;
-                  }
+   return 0;
+}
 
-               case 0x01: { /* FMADD.D */
-                     DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMADDW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     IRTemp tmp[2];
-                     Int i;
+static Int msa_MI10_load(UInt cins, UChar wd, UChar ws)   /* MI10 (0x20) */
+{
+   IRTemp t1;
+   UShort i10;
+   UChar df;
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_F64);
-                        assign(tmp[i],
-                               qop(Iop_MAddF64, rm,
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(ws),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(wt),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(wd),
-                                              mkU8(i)))));
-                     }
+   i10 = (cins & 0x03FF0000) >> 16;
+   df = cins & 0x00000003;
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[1])),
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[0]))));
-                     break;
-                  }
+   switch (df) {
+      case 0x00: { /* LD.B */
+         DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10);
+         putWReg(wd, load(Ity_V128, mkexpr(t1)));
+         break;
+      }
 
-               default:
-                  return -1;
-            }
+      case 0x01: { /* LD.H */
+         DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 1);
+#if defined (_MIPSEL)
+         putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+         putWReg(wd,
+                 unop(Iop_Reverse8sIn16_x8,
+                      load(Ity_V128, mkexpr(t1))));
+#endif
+         break;
+      }
 
-            break;
-         }
+      case 0x02: { /* LD.W */
+         DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 2);
+#if defined (_MIPSEL)
+         putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+         putWReg(wd,
+                 unop(Iop_Reverse8sIn32_x4,
+                      load(Ity_V128, mkexpr(t1))));
+#endif
+         break;
+      }
 
-      case 0x05: { /* FMSUB.df */
-            switch (df) {
-               case 0x00: { /* FMSUB.W */
-                     DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMADDW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     IRTemp tmp[4];
-                     Int i;
+      case 0x03: { /* LD.D */
+         DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 3);
+#if defined (_MIPSEL)
+         putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+         putWReg(wd,
+                 unop(Iop_Reverse8sIn64_x2,
+                      load(Ity_V128, mkexpr(t1))));
+#endif
+         break;
+      }
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_F32);
-                        assign(tmp[i],
-                               qop(Iop_MSubF32, rm,
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(ws),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(wt),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI32asF32,
-                                        binop(Iop_GetElem32x4,
-                                              getWReg(wd),
-                                              mkU8(i)))));
-                     }
+      default:
+         return -1;
+   }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[3])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[2]))),
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[1])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[0])))));
-                     break;
-                  }
+   return 0;
+}
 
-               case 0x01: { /* FMSUB.D */
-                     DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMADDD, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     IRTemp tmp[2];
-                     Int i;
+static Int msa_MI10_store(UInt cins, UChar wd, UChar ws)   /* MI10 (0x24) */
+{
+   IRTemp t1;
+   UShort i10;
+   UChar df;
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_F64);
-                        assign(tmp[i],
-                               qop(Iop_MSubF64, rm,
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(ws),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(wt),
-                                              mkU8(i))),
-                                   unop(Iop_ReinterpI64asF64,
-                                        binop(Iop_GetElem64x2,
-                                              getWReg(wd),
-                                              mkU8(i)))));
-                     }
+   df = cins & 0x00000003;
+   i10 = (cins & 0x03FF0000) >> 16;
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[1])),
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[0]))));
-                     break;
-                  }
+   switch (df) {
+      case 0x00: { /* ST.B */
+         DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10);
+         store(mkexpr(t1), getWReg(wd));
+         break;
+      }
 
-               default:
-                  return -1;
-            }
+      case 0x01: { /* ST.H */
+         DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 1);
+#if defined (_MIPSEL)
+         store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+         store(mkexpr(t1),
+               unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
+#endif
+         break;
+      }
 
-            break;
-         }
+      case 0x02: { /* ST.W */
+         DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 2);
+#if defined (_MIPSEL)
+         store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+         store(mkexpr(t1),
+               unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
+#endif
+         break;
+      }
 
-      case 0x07: { /* FEXP2.df */
-            switch (df) {
-               case 0x00: { /* FEXP2.W */
-                     DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FEXP2W, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Scale2_32Fx4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x03: { /* ST.D */
+         DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
+         LOAD_STORE_PATTERN_MSA(i10 << 3);
+#if defined (_MIPSEL)
+         store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+         store(mkexpr(t1),
+               unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
+#endif
+         break;
+      }
 
-               case 0x01: { /* FEXP2.D */
-                     DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FEXP2D, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_Scale2_64Fx2, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      default:
+         return -1;
+   }
 
-               default:
-                  return -1;
-            }
+   return 0;
+}
 
-            break;
-         }
+/*------------------------------------------------------------*/
+/*---   Disassemble a single MIPS MSA (SIMD) instruction   ---*/
+/*---   Return values:                                     ---*/
+/*---       0: Success                                     ---*/
+/*---      -1: Decode failure (unknown instruction)        ---*/
+/*---      -2: Illegal instruction                         ---*/
+/*------------------------------------------------------------*/
+static Int disMSAInstr_MIPS_WRK ( UInt cins )
+{
+   UChar minor_opcode, wd, ws;
 
-      case 0x08: { /* FEXDO.df */
-            switch (df) {
-               case 0x00: { /* FEXDO.H */
-                     DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FEXDOH, 2);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1,
-                            unop(Iop_F32toF16x4_DEP,
-                                 getWReg(ws)));
-                     assign(t2,
-                            unop(Iop_F32toF16x4_DEP,
-                                 getWReg(wt)));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t1), mkexpr(t2)));
-                     break;
-                  }
+   vassert(has_msa);
+   vassert((cins & 0xFC000000) == 0x78000000);
 
-               case 0x01: { /* FEXDO.W */
-                     DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FEXDOW, 2);
-                     t1 = newTemp(Ity_I32);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            unop(Iop_ReinterpF32asI32,
-                                 binop(Iop_F64toF32, rm,
-                                       unop(Iop_ReinterpI64asF64,
-                                            unop(Iop_V128to64,
-                                                 getWReg(ws))))));
-                     assign(t2,
-                            unop(Iop_ReinterpF32asI32,
-                                 binop(Iop_F64toF32, rm,
-                                       unop(Iop_ReinterpI64asF64,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(ws))))));
-                     assign(t3,
-                            unop(Iop_ReinterpF32asI32,
-                                 binop(Iop_F64toF32, rm,
-                                       unop(Iop_ReinterpI64asF64,
-                                            unop(Iop_V128to64,
-                                                 getWReg(wt))))));
-                     assign(t4,
-                            unop(Iop_ReinterpF32asI32,
-                                 binop(Iop_F64toF32, rm,
-                                       unop(Iop_ReinterpI64asF64,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(wt))))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         mkexpr(t2), mkexpr(t1)),
-                                   binop(Iop_32HLto64,
-                                         mkexpr(t4), mkexpr(t3))));
-                     break;
-                  }
+   minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
+   wd = (cins & 0x000007C0) >> 6;
+   ws = (cins & 0x0000F800) >> 11;
 
-               default:
-                  return -1;
-            }
+   switch (minor_opcode) {
+      case 0x0:
+         return msa_I8_logical(cins, wd, ws);
 
-            break;
-         }
+      case 0x01:
+         return msa_I8_branch(cins, wd, ws);
 
-      case 0x0A: { /* FTQ.df */
-            switch (df) {
-               case 0x00: { /* FTQ.H */
-                     DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FTQH, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_F32x4_2toQ16x8, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x02:
+         return msa_I8_shift(cins, wd, ws);
 
-               case 0x01: { /* FTQ.W */
-                     DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FTQW, 2);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     putWReg(wd,
-                             triop(Iop_F64x2_2toQ32x4, rm,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x06:
+         return msa_I5_06(cins, wd, ws);
 
-               default:
-                  return -1;
-            }
+      case 0x07:
+         return msa_I5_07(cins, wd, ws);
 
-            break;
-         }
+      case 0x09:
+         return msa_BIT_09(cins, wd, ws);
 
-      case 0x0C: { /* FMIN.df */
-            switch (df) {
-               case 0x00: { /* FMIN.W */
-                     DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMINW, 2);
-                     putWReg(wd,
-                             binop(Iop_Min32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x0A:
+         return msa_BIT_0A(cins, wd, ws);
 
-               case 0x01: { /* FMIN.D */
-                     DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMINW, 2);
-                     putWReg(wd,
-                             binop(Iop_Min64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x0D:
+         return msa_3R_0D(cins, wd, ws);
 
-               default:
-                  return -1;
-            }
+      case 0x0E:
+         return msa_3R_0E(cins, wd, ws);
 
-            break;
-         }
+      case 0x0F:
+         return msa_3R_0F(cins, wd, ws);
 
-      case 0x0D: { /* FMIN_A.df */
-            switch (df) {
-               case 0x00: { /* FMIN_A.W */
-                     DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMINAW, 2);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFF7FFFFFFF),
-                                        mkU64(0x7FFFFFFF7FFFFFFF))));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  getWReg(wt),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFF7FFFFFFF),
-                                        mkU64(0x7FFFFFFF7FFFFFFF))));
-                     assign(t3,
-                            binop(Iop_Min32Fx4,
-                                  mkexpr(t2), mkexpr(t1)));
-                     assign(t4,
-                         binop(Iop_AndV128,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128,
-                                       binop(Iop_CmpUN32Fx4,
-                                             mkexpr(t3),
-                                             mkexpr(t3))),
-                                  binop(Iop_OrV128,
-                                     binop(Iop_AndV128,
-                                           binop(Iop_CmpEQ32Fx4,
-                                                 mkexpr(t1),
-                                                 mkexpr(t2)),
-                                           binop(Iop_OrV128,
-                                                 getWReg(ws),
-                                                 getWReg(wt))),
-                                     binop(Iop_OrV128,
-                                           binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN32Fx4,
-                                                       mkexpr(t1),
-                                                       mkexpr(t1)),
-                                                 binop(Iop_CmpLT32Fx4,
-                                                       mkexpr(t3),
-                                                       mkexpr(t1))),
-                                           getWReg(wt)),
-                                           binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN32Fx4,
-                                                       mkexpr(t2),
-                                                       mkexpr(t2)),
-                                                 binop(Iop_CmpLT32Fx4,
-                                                       mkexpr(t3),
-                                                       mkexpr(t2))),
-                                                 getWReg(ws))))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x8000000080000000),
-                                  mkU64(0x8000000080000000))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3), mkexpr(t4)));
-                     break;
-                  }
+      case 0x10:
+         return msa_3R_10(cins, wd, ws);
 
-               case 0x01: { /* FMIN_A.D */
-                     DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMINAD, 2);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFFFFFFFFFF),
-                                        mkU64(0x7FFFFFFFFFFFFFFF))));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  getWReg(wt),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFFFFFFFFFF),
-                                        mkU64(0x7FFFFFFFFFFFFFFF))));
-                     assign(t3,
-                            binop(Iop_Min64Fx2,
-                                  mkexpr(t2), mkexpr(t1)));
-                     assign(t4,
-                         binop(Iop_AndV128,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128,
-                                       binop(Iop_CmpUN64Fx2,
-                                             mkexpr(t3),
-                                             mkexpr(t3))),
-                                  binop(Iop_OrV128,
-                                     binop(Iop_AndV128,
-                                           binop(Iop_CmpEQ64Fx2,
-                                                 mkexpr(t1),
-                                                 mkexpr(t2)),
-                                           binop(Iop_OrV128,
-                                                 getWReg(ws),
-                                                 getWReg(wt))),
-                                     binop(Iop_OrV128,
-                                        binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN64Fx2,
-                                                       mkexpr(t1),
-                                                       mkexpr(t1)),
-                                                 binop(Iop_CmpLT64Fx2,
-                                                       mkexpr(t3),
-                                                       mkexpr(t1))),
-                                              getWReg(wt)),
-                                        binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN64Fx2,
-                                                       mkexpr(t2),
-                                                       mkexpr(t2)),
-                                                 binop(Iop_CmpLT64Fx2,
-                                                       mkexpr(t3),
-                                                       mkexpr(t2))),
-                                              getWReg(ws))))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x8000000000000000),
-                                  mkU64(0x8000000000000000))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3), mkexpr(t4)));
-                     break;
-                  }
+      case 0x11:
+         return msa_3R_11(cins, wd, ws);
 
-               default:
-                  return -1;
-            }
+      case 0x12:
+         return msa_3R_12(cins, wd, ws);
 
-            break;
-         }
+      case 0x13:
+         return msa_3R_13(cins, wd, ws);
 
-      case 0x0E: { /* FMAX.df */
-            switch (df) {
-               case 0x00: { /* FMAX.W */
-                     DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMAXW, 2);
-                     putWReg(wd,
-                             binop(Iop_Max32Fx4,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x14:
+         return msa_3R_14(cins, wd, ws);
 
-               case 0x01: { /* FMAX.D */
-                     DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMAXW, 2);
-                     putWReg(wd,
-                             binop(Iop_Max64Fx2,
-                                   getWReg(ws),
-                                   getWReg(wt)));
-                     break;
-                  }
+      case 0x15:
+         return msa_3R_15(cins, wd, ws);
 
-               default:
-                  return -1;
-            }
+      case 0x19:
+         return msa_ELM(cins, wd, ws);
 
-            break;
-         }
+      case 0x1A:
+         return msa_3R_1A(cins, wd, ws);
 
-      case 0x0F: { /* FMAX_A.df */
-            switch (df) {
-               case 0x00: { /* FMAX_A.W */
-                     DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMAXAW, 2);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFF7FFFFFFF),
-                                        mkU64(0x7FFFFFFF7FFFFFFF))));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  getWReg(wt),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFF7FFFFFFF),
-                                        mkU64(0x7FFFFFFF7FFFFFFF))));
-                     assign(t3,
-                            binop(Iop_Max32Fx4,
-                                  mkexpr(t2), mkexpr(t1)));
-                     assign(t4,
-                         binop(Iop_AndV128,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128,
-                                       binop(Iop_CmpUN32Fx4,
-                                             mkexpr(t3),
-                                             mkexpr(t3))),
-                                  binop(Iop_OrV128,
-                                     binop(Iop_AndV128,
-                                           binop(Iop_CmpEQ32Fx4,
-                                                 mkexpr(t1),
-                                                 mkexpr(t2)),
-                                           binop(Iop_AndV128,
-                                                 getWReg(ws),
-                                                 getWReg(wt))),
-                                     binop(Iop_OrV128,
-                                        binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN32Fx4,
-                                                       mkexpr(t1),
-                                                       mkexpr(t1)),
-                                                 binop(Iop_CmpLT32Fx4,
-                                                       mkexpr(t1),
-                                                       mkexpr(t3))),
-                                              getWReg(wt)),
-                                        binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN32Fx4,
-                                                       mkexpr(t2),
-                                                       mkexpr(t2)),
-                                                 binop(Iop_CmpLT32Fx4,
-                                                       mkexpr(t2),
-                                                       mkexpr(t3))),
-                                              getWReg(ws))))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x8000000080000000),
-                                  mkU64(0x8000000080000000))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3), mkexpr(t4)));
-                     break;
-                  }
+      case 0x1B:
+         return msa_3R_1B(cins, wd, ws);
 
-               case 0x01: { /* FMAX_A.D */
-                     DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FMAXAD, 2);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFFFFFFFFFF),
-                                        mkU64(0x7FFFFFFFFFFFFFFF))));
-                     assign(t2,
-                            binop(Iop_AndV128,
-                                  getWReg(wt),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FFFFFFFFFFFFFFF),
-                                        mkU64(0x7FFFFFFFFFFFFFFF))));
-                     assign(t3,
-                            binop(Iop_Max64Fx2,
-                                  mkexpr(t2), mkexpr(t1)));
-                     assign(t4,
-                         binop(Iop_AndV128,
-                            binop(Iop_AndV128,
-                                  unop(Iop_NotV128,
-                                       binop(Iop_CmpUN64Fx2,
-                                             mkexpr(t3),
-                                             mkexpr(t3))),
-                                  binop(Iop_OrV128,
-                                     binop(Iop_AndV128,
-                                           binop(Iop_CmpEQ64Fx2,
-                                                 mkexpr(t1),
-                                                 mkexpr(t2)),
-                                           binop(Iop_AndV128,
-                                                 getWReg(ws),
-                                                 getWReg(wt))),
-                                     binop(Iop_OrV128,
-                                           binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN64Fx2,
-                                                       mkexpr(t1),
-                                                       mkexpr(t1)),
-                                                 binop(Iop_CmpLT64Fx2,
-                                                       mkexpr(t1),
-                                                       mkexpr(t3))),
-                                                 getWReg(wt)),
-                                           binop(Iop_AndV128,
-                                              binop(Iop_OrV128,
-                                                 binop(Iop_CmpUN64Fx2,
-                                                       mkexpr(t2),
-                                                       mkexpr(t2)),
-                                                 binop(Iop_CmpLT64Fx2,
-                                                       mkexpr(t2),
-                                                       mkexpr(t3))),
-                                                 getWReg(ws))))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x8000000000000000),
-                                  mkU64(0x8000000000000000))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   mkexpr(t3), mkexpr(t4)));
-                     break;
-                  }
+      case 0x1C:
+         return msa_3R_1C(cins, wd, ws);
 
-               default:
-                  return -1;
-            }
+      case 0x1E:
+         if ((cins & 0x03000000) == 0)
+            return msa_VEC(cins, wd, ws);
+         else if ((cins & 0x00200000) == 0)
+            return msa_2R(cins, wd, ws);
+         else
+            return msa_2RF(cins, wd, ws);
 
-            break;
-         }
+      case 0x20:
+         return msa_MI10_load(cins, wd, ws);
 
-      default:
-         return -1;
+      case 0x24:
+         return msa_MI10_store(cins, wd, ws);
    }
 
-   return 0;
+   return -1;
 }
 
-static Int msa_3R_1C(UInt cins, UChar wd, UChar ws) { /* 3R (0x1C) */
-   IRTemp t1, t2, t3, t4, t5, t6;
-   UShort operation;
-   UChar df, wt;
+/*------------------------------------------------------------*/
+/*---              DSP to IR function                      ---*/
+/*------------------------------------------------------------*/
 
-   operation = (cins & 0x03C00000) >> 22;
-   df = (cins & 0x00200000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+extern UInt disDSPInstr_MIPS_WRK ( UInt );
 
-   switch (operation) {
-      case 0x01: { /* FCOR.df */
-            switch (df) {
-               case 0x00: { /* FCOR.W */
-                     DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCORW, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpUN32Fx4,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+/*------------------------------------------------------------*/
+/*---          Disassemble a single instruction            ---*/
+/*------------------------------------------------------------*/
 
-               case 0x01: { /* FCOR.D */
-                     DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCORD, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpUN64Fx2,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+/* Disassemble a single instruction into IR. The instruction is
+   located in host memory at guest_instr, and has guest IP of
+   guest_PC_curr_instr, which will have been set before the call
+   here. */
 
-               default:
-                  return -1;
+
+static UInt disInstr_MIPS_WRK_Special(UInt cins, const VexArchInfo* archinfo,
+                                      const VexAbiInfo*  abiinfo, DisResult* dres,
+                                      IRStmt** bstmt, IRExpr** lastn,
+                                      Bool(*resteerOkFn) (/*opaque */void *,
+                                            Addr),
+                                      void*        callback_opaque)
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5;
+   UInt rs, rt, rd, sa, tf, function, trap_code, imm, instr_index, rot, sel;
+   /* Additional variables for instruction fields in DSP ASE insructions */
+   UInt ac;
+
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+   tf = get_tf(cins);
+   sel = get_sel(cins);
+   instr_index = get_instr_index(cins);
+   trap_code = get_code(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+   ac = get_acNo(cins);
+
+   switch (function) {
+      case 0x00: {  /* SLL */
+         DIP("sll r%u, r%u, %u", rd, rt, sa);
+         IRTemp tmpRt32 = newTemp(Ity_I32);
+         IRTemp tmpSh32 = newTemp(Ity_I32);
+         IRTemp tmpRd = newTemp(Ity_I64);
+
+         if (mode64) {
+            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+            assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
+            assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+            putIReg(rd, mkexpr(tmpRd));
+         } else
+            SXX_PATTERN(Iop_Shl32);
+
+         break;
+      }
+
+      case 0x01: {  /* MOVCI */
+         UInt mov_cc = get_mov_cc(cins);
+
+         if (tf == 0) {  /* MOVF */
+            DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
+            t1 = newTemp(Ity_I1);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I1);
+
+            assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                        mkU32(0x1))
+                                 ));
+            assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+            putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
+         } else if (tf == 1) {  /* MOVT */
+            DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
+            t1 = newTemp(Ity_I1);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I1);
+
+            assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                        mkU32(0x1))
+                                 ));
+            assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+            putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
+         }
+
+         break;
+      }
+
+      case 0x02: {  /* SRL */
+         rot = get_rot(cins);
+
+         if (rot) {
+            DIP("rotr r%u, r%u, %u", rd, rt, sa);
+            putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
+                                                   getIReg(rt)), sa), True));
+         } else {
+            DIP("srl r%u, r%u, %u", rd, rt, sa);
+
+            if (mode64) {
+               IRTemp tmpSh32 = newTemp(Ity_I32);
+               IRTemp tmpRt32 = newTemp(Ity_I32);
+
+               assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+               assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
+               putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+            } else {
+               SXX_PATTERN(Iop_Shr32);
             }
+         }
+
+         break;
+      }
+
+      case 0x03:  /* SRA */
+         DIP("sra r%u, r%u, %u", rd, rt, sa);
+
+         if (mode64) {
+            IRTemp tmpRt32 = newTemp(Ity_I32);
+            IRTemp tmpSh32 = newTemp(Ity_I32);
 
-            break;
-         }
+            t1 = newTemp(Ity_I64);
+            t2 = newTemp(Ity_I64);
+            t3 = newTemp(Ity_I64);
 
-      case 0x02: { /* FCUNE.df */
-            switch (df) {
-               case 0x00: { /* FCUNE.W */
-                     DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUNEW, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpEQ32Fx4,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+            assign(t1, binop(Iop_And64, getIReg(rt),  /* hi */
+                             mkU64(0xFFFFFFFF00000000ULL)));
 
-               case 0x01: { /* FCUNE.D */
-                     DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCUNED, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpEQ64Fx2,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+            assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
 
-               default:
-                  return -1;
-            }
+            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+            assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
 
-            break;
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+         } else {
+            SXX_PATTERN(Iop_Sar32);
          }
 
-      case 0x03: { /* FCNE.df */
-            switch (df) {
-               case 0x00: { /* FCNE.W */
-                     DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCNEW, 2);
-                     putWReg(wd,
-                             binop(Iop_XorV128,
-                                   unop(Iop_NotV128,
-                                        binop(Iop_CmpEQ32Fx4,
-                                              getWReg(ws),
-                                              getWReg(wt))),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
-
-               case 0x01: { /* FCNE.D */
-                     DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FCNED, 2);
-                     putWReg(wd,
-                             binop(Iop_XorV128,
-                                   unop(Iop_NotV128,
-                                        binop(Iop_CmpEQ64Fx2,
-                                              getWReg(ws),
-                                              getWReg(wt))),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
 
-               default:
-                  return -1;
-            }
+      case 0x04: {  /* SLLV */
+         DIP("sllv r%u, r%u, r%u", rd, rt, rs);
 
-            break;
+         if (mode64) {
+            IRTemp tmpRs8 = newTemp(Ity_I8);
+            IRTemp tmpRt32 = newTemp(Ity_I32);
+            IRTemp tmpSh32 = newTemp(Ity_I32);
+            IRTemp tmp = newTemp(ty);
+            assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
+                              mkSzImm(ty, 31)));
+            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+            assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+         } else {
+            SXXV_PATTERN(Iop_Shl32);
          }
 
-      case 0x04: { /* MUL_Q.df */
-            switch (df) {
-               case 0x00: { /* MUL_Q.H */
-                     DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_QDMulHi16Sx8,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MUL_Q.W */
-                     DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3,
-                            binop(Iop_QDMulHi32Sx4,
-                                  mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x05: { /* LSA */
+         UInt imm2 = (imm & 0xC0) >> 6;
 
-               default:
-                  return -1;
-            }
+         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
+            DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
 
+            if (mode64) {
+               DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+               putIReg(rd, unop(Iop_32Sto64,
+                                binop(Iop_Add32,
+                                      binop(Iop_Shl32,
+                                            unop(Iop_64to32, getIReg(rs)),
+                                            mkU8(imm2 + 1)),
+                                      unop(Iop_64to32, getIReg(rt)))));
+               break;
+            } else {
+               DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+               putIReg(rd, binop(Iop_Add32,
+                                 binop(Iop_Shl32,
+                                       getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
+               break;
+            }
+         } else {
+            ILLEGAL_INSTRUCTON;
             break;
          }
+      }
 
-      case 0x05: { /* MADD_Q.df */
-            switch (df) {
-               case 0x00: { /* MADD_Q.W */
-                     DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(ws), mkU8(16)));
-                     assign(t3, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(16)));
-                     assign(t4, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(wt), mkU8(16)));
-                     assign(t5,
-                         binop(Iop_Add32x4,
-                            binop(Iop_ShlN32x4,
-                                  binop(Iop_SarN32x4,
-                                     binop(Iop_InterleaveEvenLanes16x8,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(16)),
-                                  mkU8(15)),
-                            binop(Iop_Mul32x4,
-                                  mkexpr(t1), mkexpr(t3))));
-                     assign(t6,
-                            binop(Iop_Add32x4,
-                                  binop(Iop_ShlN32x4,
-                                        binop(Iop_SarN32x4,
-                                              getWReg(wd),
-                                              mkU8(16)),
-                                        mkU8(15)),
-                                  binop(Iop_Mul32x4,
-                                        mkexpr(t2), mkexpr(t4))));
-                     putWReg(wd,
-                             binop(Iop_InterleaveEvenLanes16x8,
-                                   binop(Iop_QandQSarNnarrow32Sto16Sx4,
-                                         mkexpr(t6), mkU8(15)),
-                                   binop(Iop_QandQSarNnarrow32Sto16Sx4,
-                                         mkexpr(t5), mkU8(15))));
-                     break;
-                  }
+      case 0x06: { /* SRLV */
+         rot = get_rotv(cins);
 
-               case 0x01: { /* MADD_Q.W */
-                     DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(ws), mkU8(32)));
-                     assign(t3, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(32)));
-                     assign(t4, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(wt), mkU8(32)));
-                     assign(t5,
-                         binop(Iop_Add64x2,
-                            binop(Iop_ShlN64x2,
-                                  binop(Iop_SarN64x2,
-                                     binop(Iop_InterleaveEvenLanes32x4,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(32)),
-                                  mkU8(31)),
-                            binop(Iop_64HLtoV128,
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t3))),
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128to64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128to64,
-                                             mkexpr(t3))))));
-                     assign(t6,
-                            binop(Iop_Add64x2,
-                                  binop(Iop_ShlN64x2,
-                                        binop(Iop_SarN64x2,
-                                              getWReg(wd),
-                                              mkU8(32)),
-                                        mkU8(31)),
-                                  binop(Iop_64HLtoV128,
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t4))),
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t4))))));
-                     putWReg(wd,
-                             binop(Iop_InterleaveEvenLanes32x4,
-                                   binop(Iop_QandQSarNnarrow64Sto32Sx2,
-                                         mkexpr(t6), mkU8(31)),
-                                   binop(Iop_QandQSarNnarrow64Sto32Sx2,
-                                         mkexpr(t5), mkU8(31))));
-                     break;
-                  }
+         if (rot) {
+            DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
+            putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
+                                                    getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
+            break;
+         } else {  /* SRLV */
+            DIP("srlv r%u, r%u, r%u", rd, rt, rs);
 
-               default:
-                  return -1;
+            if (mode64) {
+               SXXV_PATTERN64(Iop_Shr32);
+            } else {
+               SXXV_PATTERN(Iop_Shr32);
             }
 
             break;
          }
+      }
 
-      case 0x06: { /* MSUB_Q.df */
-            switch (df) {
-               case 0x00: { /* MSUB_Q.H */
-                     DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(ws), mkU8(16)));
-                     assign(t3, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(16)));
-                     assign(t4, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(wt), mkU8(16)));
-                     assign(t5,
-                         binop(Iop_Sub32x4,
-                            binop(Iop_ShlN32x4,
-                               binop(Iop_SarN32x4,
-                                     binop(Iop_InterleaveEvenLanes16x8,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(16)),
-                               mkU8(15)),
-                            binop(Iop_Mul32x4,
-                                  mkexpr(t1), mkexpr(t3))));
-                     assign(t6,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_ShlN32x4,
-                                        binop(Iop_SarN32x4,
-                                              getWReg(wd),
-                                              mkU8(16)),
-                                        mkU8(15)),
-                                  binop(Iop_Mul32x4,
-                                        mkexpr(t2), mkexpr(t4))));
-                     putWReg(wd,
-                             binop(Iop_InterleaveEvenLanes16x8,
-                                   binop(Iop_QandQSarNnarrow32Sto16Sx4,
-                                         mkexpr(t6), mkU8(15)),
-                                   binop(Iop_QandQSarNnarrow32Sto16Sx4,
-                                         mkexpr(t5), mkU8(15))));
-                     break;
-                  }
+      case 0x07:  /* SRAV */
+         DIP("srav r%u, r%u, r%u", rd, rt, rs);
 
-               case 0x01: { /* MSUB_Q.W */
-                     DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(ws), mkU8(32)));
-                     assign(t3, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(32)));
-                     assign(t4, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(wt), mkU8(32)));
-                     assign(t5,
-                         binop(Iop_Sub64x2,
-                               binop(Iop_ShlN64x2,
-                                  binop(Iop_SarN64x2,
-                                     binop(Iop_InterleaveEvenLanes32x4,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(32)),
-                                  mkU8(31)),
-                               binop(Iop_64HLtoV128,
-                                     binop(Iop_Mul64,
-                                           unop(Iop_V128HIto64,
-                                                mkexpr(t1)),
-                                           unop(Iop_V128HIto64,
-                                                mkexpr(t3))),
-                                     binop(Iop_Mul64,
-                                           unop(Iop_V128to64,
-                                                mkexpr(t1)),
-                                           unop(Iop_V128to64,
-                                                mkexpr(t3))))));
-                     assign(t6,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_ShlN64x2,
-                                        binop(Iop_SarN64x2,
-                                              getWReg(wd),
-                                              mkU8(32)),
-                                        mkU8(31)),
-                                  binop(Iop_64HLtoV128,
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t4))),
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t4))))));
-                     putWReg(wd,
-                             binop(Iop_InterleaveEvenLanes32x4,
-                                   binop(Iop_QandQSarNnarrow64Sto32Sx2,
-                                         mkexpr(t6), mkU8(31)),
-                                   binop(Iop_QandQSarNnarrow64Sto32Sx2,
-                                         mkexpr(t5), mkU8(31))));
-                     break;
-                  }
+         if (mode64) {
+            IRTemp tmpRt32 = newTemp(Ity_I32);
+            IRTemp tmpSh32 = newTemp(Ity_I32);
 
-               default:
-                  return -1;
-            }
+            t1 = newTemp(Ity_I64);
+            t2 = newTemp(Ity_I64);
+            t3 = newTemp(Ity_I64);
+            t4 = newTemp(Ity_I8);
 
-            break;
-         }
+            assign(t4, unop(Iop_32to8, binop(Iop_And32,
+                                             mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
 
-      case 0x09: { /* FSOR.df */
-            switch (df) {
-               case 0x00: { /* FSOR.W */
-                     DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSORW, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpUN32Fx4,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+            assign(t1, binop(Iop_And64, getIReg(rt),  /* hi */
+                             mkU64(0xFFFFFFFF00000000ULL)));
 
-               case 0x01: { /* FSOR.D */
-                     DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSORD, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpUN64Fx2,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+            assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
 
-               default:
-                  return -1;
-            }
+            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+            assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
 
-            break;
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+         } else {
+            SXXV_PATTERN(Iop_Sar32);
          }
 
-      case 0x0A: { /* FSUNE.df */
-            switch (df) {
-               case 0x00: { /* FSUNE.W */
-                     DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUNEW, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpEQ32Fx4,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+         break;
 
-               case 0x01: { /* FSUNE.D */
-                     DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSUNED, 2);
-                     putWReg(wd,
-                             unop(Iop_NotV128,
-                                  binop(Iop_CmpEQ64Fx2,
-                                        getWReg(ws),
-                                        getWReg(wt))));
-                     break;
-                  }
+      case 0x08:  /* JR */
+         DIP("jr r%u", rs);
+         t0 = newTemp(ty);
+         assign(t0, getIReg(rs));
+         *lastn = mkexpr(t0);
+         break;
 
-               default:
-                  return -1;
-            }
+      case 0x09:  /* JALR */
+         DIP("jalr r%u r%u", rd, rs);
 
-            break;
+         if (mode64) {
+            putIReg(rd, mkU64(guest_PC_curr_instr + 8));
+            t0 = newTemp(Ity_I64);
+            assign(t0, getIReg(rs));
+            *lastn = mkexpr(t0);
+         } else {
+            putIReg(rd, mkU32(guest_PC_curr_instr + 8));
+            t0 = newTemp(Ity_I32);
+            assign(t0, getIReg(rs));
+            *lastn = mkexpr(t0);
          }
 
-      case 0x0B: { /* FSNE.df */
-            switch (df) {
-               case 0x00: { /* FSNE.W */
-                     DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSNEW, 2);
-                     putWReg(wd,
-                             binop(Iop_XorV128,
-                                   unop(Iop_NotV128,
-                                        binop(Iop_CmpEQ32Fx4,
-                                              getWReg(ws),
-                                              getWReg(wt))),
-                                   binop(Iop_CmpUN32Fx4,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+         break;
 
-               case 0x01: { /* FSNE.D */
-                     DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
-                     calculateMSACSR(ws, wt, FSNED, 2);
-                     putWReg(wd,
-                             binop(Iop_XorV128,
-                                   unop(Iop_NotV128,
-                                        binop(Iop_CmpEQ64Fx2,
-                                              getWReg(ws),
-                                              getWReg(wt))),
-                                   binop(Iop_CmpUN64Fx2,
-                                         getWReg(ws),
-                                         getWReg(wt))));
-                     break;
-                  }
+      case 0x0A: {  /* MOVZ */
+         DIP("movz r%u, r%u, r%u", rd, rs, rt);
+         t1 = newTemp(ty);
+         t2 = newTemp(ty);
 
-               default:
-                  return -1;
-            }
+         if (mode64) {
+            assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
+                                              getIReg(rt), mkU64(0x0)))));
+            assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
+                                              getIReg(rt), mkU64(0x0)))));
+            putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
+                                               mkexpr(t1)), binop(Iop_And64, getIReg(rd), mkexpr(t2))));
+         } else {
+            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+                                              mkU32(0x0))));
+            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+                                              mkU32(0x0))));
+            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+                                               mkexpr(t1)), binop(Iop_And32, getIReg(rd),
+                                                     mkexpr(t2))));
+         }
 
-            break;
+         break;
+      }
+
+      case 0x0B: {  /* MOVN */
+         DIP("movn r%u, r%u, r%u", rd, rs, rt);
+         t1 = newTemp(ty);
+         t2 = newTemp(ty);
+
+         if (mode64) {
+            assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
+                                              getIReg(rt), mkU64(0x0)))));
+            assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
+                                              getIReg(rt), mkU64(0x0)))));
+            putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
+                                               mkexpr(t2)), binop(Iop_And64, getIReg(rd),
+                                                     mkexpr(t1))));
+         } else {
+            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+                                              mkU32(0x0))));
+            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+                                              mkU32(0x0))));
+            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+                                               mkexpr(t2)), binop(Iop_And32, getIReg(rd),
+                                                     mkexpr(t1))));
          }
 
-      case 0x0C: { /* MULR_Q.df */
-            switch (df) {
-               case 0x00: { /* MULR_Q.H */
-                     DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QRDMulHi16Sx8,
-                                      mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: { /* MULR_Q.W */
-                     DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
-                     assign(t2, getWReg(wt));
-                     assign(t3, binop(Iop_QRDMulHi32Sx4,
-                                      mkexpr(t1), mkexpr(t2)));
-                     putWReg(wd, mkexpr(t3));
-                     break;
-                  }
+      case 0x0C:  /* SYSCALL */
+         DIP("syscall");
 
-               default:
-                  return -1;
-            }
+         if (mode64)
+            putPC(mkU64(guest_PC_curr_instr + 4));
+         else
+            putPC(mkU32(guest_PC_curr_instr + 4));
 
-            break;
-         }
+         dres->jk_StopHere = Ijk_Sys_syscall;
+         dres->whatNext    = Dis_StopHere;
+         break;
 
-      case 0x0D: { /* MADDR_Q.df */
-            switch (df) {
-               case 0x00: { /* MADDR_Q.W */
-                     DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(ws), mkU8(16)));
-                     assign(t3, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(16)));
-                     assign(t4, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(wt), mkU8(16)));
-                     assign(t5,
-                         binop(Iop_Add32x4,
-                            binop(Iop_ShlN32x4,
-                               binop(Iop_SarN32x4,
-                                     binop(Iop_InterleaveEvenLanes16x8,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(16)),
-                               mkU8(15)),
-                            binop(Iop_Mul32x4,
-                                  mkexpr(t1), mkexpr(t3))));
-                     assign(t6,
-                            binop(Iop_Add32x4,
-                                  binop(Iop_ShlN32x4,
-                                        binop(Iop_SarN32x4,
-                                              getWReg(wd),
-                                              mkU8(16)),
-                                        mkU8(15)),
-                                  binop(Iop_Mul32x4,
-                                        mkexpr(t2), mkexpr(t4))));
-                     putWReg(wd,
-                          binop(Iop_InterleaveEvenLanes16x8,
-                                binop(Iop_QandQRSarNnarrow32Sto16Sx4,
-                                      mkexpr(t6), mkU8(15)),
-                                binop(Iop_QandQRSarNnarrow32Sto16Sx4,
-                                      mkexpr(t5), mkU8(15))));
-                     break;
-                  }
+      case 0x0D:  /* BREAK */
+         DIP("break 0x%x", trap_code);
 
-               case 0x01: { /* MADDR_Q.D */
-                     DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(ws), mkU8(32)));
-                     assign(t3, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(32)));
-                     assign(t4, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(wt), mkU8(32)));
-                     assign(t5,
-                         binop(Iop_Add64x2,
-                            binop(Iop_ShlN64x2,
-                               binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wd),
-                                        getWReg(wd)),
-                                  mkU8(32)),
-                               mkU8(31)),
-                            binop(Iop_64HLtoV128,
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t3))),
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128to64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128to64,
-                                             mkexpr(t3))))));
-                     assign(t6,
-                            binop(Iop_Add64x2,
-                                  binop(Iop_ShlN64x2,
-                                        binop(Iop_SarN64x2,
-                                              getWReg(wd),
-                                              mkU8(32)),
-                                        mkU8(31)),
-                                  binop(Iop_64HLtoV128,
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t4))),
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t4))))));
-                     putWReg(wd,
-                          binop(Iop_InterleaveEvenLanes32x4,
-                                binop(Iop_QandQRSarNnarrow64Sto32Sx2,
-                                      mkexpr(t6), mkU8(31)),
-                                binop(Iop_QandQRSarNnarrow64Sto32Sx2,
-                                      mkexpr(t5), mkU8(31))));
-                     break;
-                  }
+         if (mode64)
+            jmp_lit64(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
+         else
+            jmp_lit32(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
 
-               default:
-                  return -1;
-            }
+         vassert(dres->whatNext == Dis_StopHere);
+         break;
 
-            break;
-         }
+      case 0x0F:  /* SYNC */
+         DIP("sync 0x%x", sel);
+         /* Just ignore it. */
+         break;
 
-      case 0x0E: { /* MSUBR_Q.df */
-            switch (df) {
-               case 0x00: { /* MSUBR_Q.W */
-                     DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(ws), mkU8(16)));
-                     assign(t3, // even
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(16)));
-                     assign(t4, // odd
-                            binop(Iop_SarN32x4,
-                                  getWReg(wt), mkU8(16)));
-                     assign(t5,
-                         binop(Iop_Sub32x4,
-                            binop(Iop_ShlN32x4,
-                                  binop(Iop_SarN32x4,
-                                     binop(Iop_InterleaveEvenLanes16x8,
-                                           getWReg(wd),
-                                           getWReg(wd)),
-                                     mkU8(16)),
-                                  mkU8(15)),
-                            binop(Iop_Mul32x4,
-                                  mkexpr(t1), mkexpr(t3))));
-                     assign(t6,
-                            binop(Iop_Sub32x4,
-                                  binop(Iop_ShlN32x4,
-                                        binop(Iop_SarN32x4,
-                                              getWReg(wd),
-                                              mkU8(16)),
-                                        mkU8(15)),
-                                  binop(Iop_Mul32x4,
-                                        mkexpr(t2), mkexpr(t4))));
-                     putWReg(wd,
-                          binop(Iop_InterleaveEvenLanes16x8,
-                                binop(Iop_QandQRSarNnarrow32Sto16Sx4,
-                                      mkexpr(t6), mkU8(15)),
-                                binop(Iop_QandQRSarNnarrow32Sto16Sx4,
-                                      mkexpr(t5), mkU8(15))));
-                     break;
-                  }
+      case 0x10: {  /* MFHI, CLZ R6 */
+         if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("clz r%u, r%u", rd, rs);
 
-               case 0x01: { /* MSUBR_Q.D */
-                     DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     t5 = newTemp(Ity_V128);
-                     t6 = newTemp(Ity_V128);
-                     assign(t1, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(ws), mkU8(32)));
-                     assign(t3, // even
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wt),
-                                        getWReg(wt)),
-                                  mkU8(32)));
-                     assign(t4, // odd
-                            binop(Iop_SarN64x2,
-                                  getWReg(wt), mkU8(32)));
-                     assign(t5,
-                         binop(Iop_Sub64x2,
-                            binop(Iop_ShlN64x2,
-                               binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        getWReg(wd),
-                                        getWReg(wd)),
-                                  mkU8(32)),
-                               mkU8(31)),
-                            binop(Iop_64HLtoV128,
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128HIto64,
-                                             mkexpr(t3))),
-                                  binop(Iop_Mul64,
-                                        unop(Iop_V128to64,
-                                             mkexpr(t1)),
-                                        unop(Iop_V128to64,
-                                             mkexpr(t3))))));
-                  assign(t6,
-                            binop(Iop_Sub64x2,
-                                  binop(Iop_ShlN64x2,
-                                        binop(Iop_SarN64x2,
-                                              getWReg(wd),
-                                              mkU8(32)),
-                                        mkU8(31)),
-                                  binop(Iop_64HLtoV128,
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128HIto64,
-                                                   mkexpr(t4))),
-                                        binop(Iop_Mul64,
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t2)),
-                                              unop(Iop_V128to64,
-                                                   mkexpr(t4))))));
-                     putWReg(wd,
-                          binop(Iop_InterleaveEvenLanes32x4,
-                                binop(Iop_QandQRSarNnarrow64Sto32Sx2,
-                                      mkexpr(t6), mkU8(31)),
-                                binop(Iop_QandQRSarNnarrow64Sto32Sx2,
-                                      mkexpr(t5), mkU8(31))));
-                     break;
-                  }
+               if (mode64) {
+                  IRTemp tmpClz32 = newTemp(Ity_I32);
+                  IRTemp tmpRs32 = newTemp(Ity_I32);
 
-               default:
-                  return -1;
+                  assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+                  assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
+                  putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+               } else {
+                  t1 = newTemp(Ity_I1);
+                  assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
+                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                         mkU32(0x00000020),
+                                         unop(Iop_Clz32, getIReg(rs))));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
             }
 
             break;
-         }
+         } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+            /* If DSP is present -> DSP ASE MFHI */
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-      default:
-         return -1;
-   }
+            if (0 != retVal ) {
+               return -1;
+            }
 
-   return 0;
-}
+            break;
+         } else {
+            DIP("mfhi r%u", rd);
+            putIReg(rd, getHI());
+            break;
+         }
+      }
 
-static Int msa_ELM(UInt cins, UChar wd, UChar ws) { /* ELM (0x19) */
-   IRTemp t1, t2, t3, t4, t5;
-   IRType ty;
-   UShort operation;
-   UChar df, n;
+      case 0x11:  {  /* MTHI, CLO R6 */
+         if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("clo r%u, r%u", rd, rs);
 
-   operation = (cins & 0x03C00000) >> 22;
-   ty = mode64 ? Ity_I64 : Ity_I32;
+               if (mode64) {
+                  IRTemp tmpClo32 = newTemp(Ity_I32);
+                  IRTemp tmpRs32 = newTemp(Ity_I32);
+                  assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
 
-   switch ((cins & 0x03FF0000) >> 16) {
-      case 0x07E: /* CFCMSA */
-         DIP("CFCMSA r%d, c%d", wd, ws);
+                  t1 = newTemp(Ity_I1);
+                  assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
+                  assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
+                                              mkU32(0x00000020),
+                                              unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
 
-         switch (ws) {
-            case 0: { /* MSAIR */
-                  IRDirty *d;
-                  t1 = newTemp(Ity_I32);
-                  /* IRExpr_BBPTR() =>
-                                       Need to pass pointer to
-                                             guest state to helper. */
-                  d = unsafeIRDirty_1_N(t1, 0,
-                                        "mips_dirtyhelper_get_MSAIR",
-                                        &mips_dirtyhelper_get_MSAIR,
-                                        mkIRExprVec_0());
-                  /* d->nFxState = 0; */
-                  stmt(IRStmt_Dirty(d));
-                  putIReg(wd,
-                          mkWidenFrom32(ty, mkexpr(t1), True));
+                  putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
                   break;
+               } else {
+                  t1 = newTemp(Ity_I1);
+                  assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
+                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                         mkU32(0x00000020),
+                                         unop(Iop_Clz32,
+                                              unop(Iop_Not32, getIReg(rs)))));
                }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
 
-            case 1: /* MSACSR */
-               putIReg(wd,
-                       mkWidenFrom32(ty, getMSACSR(), True));
-               break;
+            break;
+         } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+            /* If DSP is present -> DSP ASE MTHI */
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-            default:
-               putIReg(wd,
-                       mkWidenFrom32(ty, mkU32(0), False));
-               break;
-         }
+            if (0 != retVal ) {
+               return -1;
+            }
 
-         break;
+            break;
+         } else {
+            DIP("mthi r%u", rs);
+            putHI(getIReg(rs));
+            break;
+         }
+      }
 
-      case 0x03E: /* CTCMSA */
-         DIP("CTCMSA r%d, c%d", ws, wd);
+      case 0x12:  {  /* MFLO */
+         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+            /* If DSP is present -> DSP ASE MFLO */
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-         if (wd == 1) { /* MSACSR */
-            putMSACSR(
-               binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
-                     mkU32(0x1FFFFFF)));
-         }
+            if (0 != retVal ) {
+               return -1;
+            }
 
-         break;
+            break;
+         } else {
+            switch (sa) {
+               case 0:
+                  DIP("mflo r%u", rd);
 
-      case 0x0BE: /* MOVE.V */
-         DIP("MOVE.V w%d, w%d", ws, wd);
-         putWReg(wd, getWReg(ws));
-         break;
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                        !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-      default:
-         df = (cins & 0x003F0000) >> 16;
-         if ((df & 0x38) == 0x38) {        // 11100n; dw
-            n = df & 0x01;
-            df = 0x38;
-         } else if ((df & 0x30) == 0x30) { // 1100nn; w
-            n = df & 0x03;
-            df = 0x30;
-         } else if ((df & 0x20) == 0x20) { // 100nnn; hw
-            n = df & 0x07;
-            df = 0x20;
-         } else if ((df & 0x00) == 0x00) { // 00nnnn; b
-            n = df & 0x0F;
-            df = 0x00;
-         }
+                  putIReg(rd, getLO());
+                  break;
 
-         switch (operation) {
-            case 0x00: /* SLDI.df */
-               switch (df) {
-                  case 0x00: /* SLDI.B */
-                     DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_V128);
-                     assign(t1,
-                            binop(Iop_ShrV128,
-                                  getWReg(ws),
-                                  mkU8(n << 3)));
-                     assign(t2,
-                            binop(Iop_ShlV128,
-                                  getWReg(wd),
-                                  mkU8(n ?
-                                       (16 - n) << 3 : 0)));
-                     putWReg(wd,
-                             binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-                     break;
+               case 1:
+                  DIP("dclz r%u, r%u", rd, rs);
+                  t1 = newTemp(Ity_I1);
+                  assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
+                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                         mkU64(0x00000040),
+                                         unop(Iop_Clz64, getIReg(rs))));
+                  break;
+            }
 
-                  case 0x20: /* SLDI.H */
-                     DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
+            break;
+         }
+      }
 
-                     if (n == 0) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_ShrN64x2,
-                                     getWReg(ws),
-                                     mkU8(n << 3)));
-                        assign(t2,
-                               binop(Iop_ShlN64x2,
-                                     getWReg(wd),
-                                     mkU8((8 - n) << 3)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      mkexpr(t1),
-                                      mkexpr(t2)));
-                     }
+      case 0x13:  {  /* MTLO */
+         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+            /* If DSP is present -> DSP ASE MTLO */
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                     break;
+            if (0 != retVal ) {
+               return -1;
+            }
 
-                  case 0x30: /* SLDI.W */
-                     DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
+            break;
+         } else {
+            switch (sa) {
+               case 0:
+                  DIP("mtlo r%u", rs);
 
-                     if (n == 0) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_ShrN32x4,
-                                     getWReg(ws),
-                                     mkU8(n << 3)));
-                        assign(t2,
-                               binop(Iop_ShlN32x4,
-                                     getWReg(wd),
-                                     mkU8((4 - n) << 3)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      mkexpr(t1),
-                                      mkexpr(t2)));
-                     }
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                        !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-                     break;
+                  putLO(getIReg(rs));
+                  break;
 
-                  case 0x38:  /* SLDI.D */
-                     DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
+               case 1:
+                  DIP("dclo r%u, r%u", rd, rs);
+                  t1 = newTemp(Ity_I1);
+                  assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
+                                   mkU64(0xffffffffffffffffULL)));
+                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                         mkU64(0x40),
+                                         unop(Iop_Clz64, unop(Iop_Not64,
+                                               getIReg(rs)))));
+                  break;
+            }
 
-                     if (n == 0) {
-                        putWReg(wd, getWReg(ws));
-                     } else {
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        assign(t1,
-                               binop(Iop_ShrN16x8,
-                                     getWReg(ws),
-                                     mkU8(n << 3)));
-                        assign(t2,
-                               binop(Iop_ShlN16x8,
-                                     getWReg(wd),
-                                     mkU8((2 - n) << 3)));
-                        putWReg(wd,
-                                binop(Iop_OrV128,
-                                      mkexpr(t1),
-                                      mkexpr(t2)));
-                     }
+            break;
+         }
+      }
 
-                     break;
+      case 0x15: { /* DLSA */
+         UInt imm2 = (imm & 0xC0) >> 6;
 
-                  default:
-                     return -1;
-               }
+         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
+            DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+            putIReg(rd, binop(Iop_Add64,
+                              binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
+                              getIReg(rt)));
+         } else {
+            ILLEGAL_INSTRUCTON
+         }
 
-               break;
+         break;
+      }
 
-            case 0x01: /* SPLATI.df */
-               switch (df) {
-                  case 0x00: { /* SPLATI.B */
-                        DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        t3 = newTemp(Ity_V128);
-                        t4 = newTemp(Ity_V128);
+      case 0x18:  {  /* MULT */
+         switch (sa & 0x3) {
+            case 0: {
+               if ((1 <= ac) && ( 3 >= ac)) {
+                  if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                     /* If DSP is present -> DSP ASE MULT */
+                     UInt retVal = disDSPInstr_MIPS_WRK(cins);
 
-                        if (n & 1)
-                           assign(t1,
-                                  binop(Iop_InterleaveOddLanes8x16,
-                                        getWReg(ws),
-                                        getWReg(ws)));
-                        else
-                           assign(t1,
-                                  binop(Iop_InterleaveEvenLanes8x16,
-                                        getWReg(ws),
-                                        getWReg(ws)));
+                     if (0 != retVal) {
+                        return -2;
+                     }
 
-                        n /= 2;
+                     break;
+                  } else {
+                     return -2;
+                  }
+               } else {
+                  DIP("mult r%u, r%u", rs, rt);
 
-                        if (n & 1)
-                           assign(t2,
-                                  binop(Iop_InterleaveOddLanes16x8,
-                                        mkexpr(t1), mkexpr(t1)));
-                        else
-                           assign(t2,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        mkexpr(t1), mkexpr(t1)));
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                        !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-                        n /= 2;
+                  t2 = newTemp(Ity_I64);
 
-                        if (n & 1)
-                           assign(t3,
-                                  binop(Iop_InterleaveOddLanes32x4,
-                                        mkexpr(t2), mkexpr(t2)));
-                        else
-                           assign(t3,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        mkexpr(t2), mkexpr(t2)));
+                  assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+                                   mkNarrowTo32(ty, getIReg(rt))));
 
-                        n /= 2;
+                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+                  break;
+               }
+            }
 
-                        if (n & 1)
-                           assign(t4,
-                                  binop(Iop_InterleaveHI64x2,
-                                        mkexpr(t3), mkexpr(t3)));
-                        else
-                           assign(t4,
-                                  binop(Iop_InterleaveLO64x2,
-                                        mkexpr(t3), mkexpr(t3)));
+            case 2: { /* MUL R6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("mul r%u, r%u, r%u", rs, rt, rd);
 
-                        putWReg(wd, mkexpr(t4));
-                        break;
-                     }
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Sto64,
+                                      unop(Iop_64to32,
+                                           binop(Iop_MullS32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     putIReg(rd, unop(Iop_64to32,
+                                      binop(Iop_MullS32,
+                                            getIReg(rs), getIReg(rt))));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
+               }
 
-                  case 0x20: { /* SPLATI.H */
-                        DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        t3 = newTemp(Ity_V128);
+               break;
+            }
 
-                        if (n & 1)
-                           assign(t1,
-                                  binop(Iop_InterleaveOddLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)));
-                        else
-                           assign(t1,
-                                  binop(Iop_InterleaveEvenLanes16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)));
+            case 3: {  /* MUH R6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("muh r%u, r%u, r%u", rs, rt, rd);
 
-                        n /= 2;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Sto64,
+                                      unop(Iop_64HIto32,
+                                           binop(Iop_MullS32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     putIReg(rd, unop(Iop_64HIto32,
+                                      binop(Iop_MullS32,
+                                            getIReg(rs), getIReg(rt))));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
+               }
 
-                        if (n & 1)
-                           assign(t2,
-                                  binop(Iop_InterleaveOddLanes32x4,
-                                        mkexpr(t1), mkexpr(t1)));
-                        else
-                           assign(t2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        mkexpr(t1), mkexpr(t1)));
+               break;
+            }
+         }
 
-                        n /= 2;
+         break;
+      }
 
-                        if (n & 1)
-                           assign(t3,
-                                  binop(Iop_InterleaveHI64x2,
-                                        mkexpr(t2), mkexpr(t2)));
-                        else
-                           assign(t3,
-                                  binop(Iop_InterleaveLO64x2,
-                                        mkexpr(t2), mkexpr(t2)));
+      case 0x19:  {  /* MULTU */
+         switch (sa & 0x3) {
+            case 0: {
+               if ((1 <= ac) && ( 3 >= ac)) {
+                  if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                     /* If DSP is present -> DSP ASE MULTU */
+                     UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                        putWReg(wd, mkexpr(t3));
-                        break;
+                     if (0 != retVal) {
+                        return -2;
                      }
 
-                  case 0x30: { /* SPLATI.W */
-                        DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
-                        t1 = newTemp(Ity_V128);
-                        t2 = newTemp(Ity_V128);
-                        t3 = newTemp(Ity_V128);
-                        assign(t1, getWReg(ws));
+                     break;
+                  } else {
+                     return -2;
+                  }
+               } else {
+                  DIP("multu r%u, r%u", rs, rt);
 
-                        if (n & 1)
-                           assign(t2,
-                                  binop(Iop_InterleaveOddLanes32x4,
-                                        mkexpr(t1), mkexpr(t1)));
-                        else
-                           assign(t2,
-                                  binop(Iop_InterleaveEvenLanes32x4,
-                                        mkexpr(t1), mkexpr(t1)));
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                        !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-                        n /= 2;
+                  t2 = newTemp(Ity_I64);
 
-                        if (n & 1)
-                           assign(t3,
-                                  binop(Iop_InterleaveHI64x2,
-                                        mkexpr(t2), mkexpr(t2)));
-                        else
-                           assign(t3,
-                                  binop(Iop_InterleaveLO64x2,
-                                        mkexpr(t2), mkexpr(t2)));
+                  assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+                                   mkNarrowTo32(ty, getIReg(rt))));
 
-                        putWReg(wd, mkexpr(t3));
-                        break;
-                     }
+                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+                  break;
+               }
+            }
 
-                  case 0x38: /* SPLATI.D */
-                     DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
-                     t1 = newTemp(Ity_V128);
-                     t3 = newTemp(Ity_V128);
-                     assign(t1, getWReg(ws));
+            case 2: {  /* MULU R6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("mulu r%u, r%u, r%u", rs, rt, rd);
 
-                     if (n)
-                        assign(t3,
-                               binop(Iop_InterleaveHI64x2,
-                                     mkexpr(t1), mkexpr(t1)));
-                     else
-                        assign(t3,
-                               binop(Iop_InterleaveLO64x2,
-                                     mkexpr(t1), mkexpr(t1)));
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Uto64,
+                                      unop(Iop_64to32,
+                                           binop(Iop_MullU32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     putIReg(rd, unop(Iop_64to32,
+                                      binop(Iop_MullU32,
+                                            getIReg(rs), getIReg(rt))));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
+               }
 
-                     putWReg(wd, mkexpr(t3));
-                     break;
+               break;
+            }
 
-                  default:
-                     return -1;
+            case 3: {  /* MUHU R6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("muhu r%u, r%u, r%u", rs, rt, rd);
+
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Uto64,
+                                      unop(Iop_64HIto32,
+                                           binop(Iop_MullU32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     putIReg(rd, unop(Iop_64HIto32,
+                                      binop(Iop_MullU32,
+                                            getIReg(rs), getIReg(rt))));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
                }
 
                break;
+            }
+         }
 
-            case 0x02: /* COPY_S.df */
-               switch (df) {
-                  case 0x00: /* COPY_S.B */
-                     DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
-                     t1 = newTemp(Ity_I8);
+         break;
+      }
 
-                     switch (n) {
-                        case 0:
-                           assign(t1,
-                                  unop(Iop_32to8,
-                                       unop(Iop_V128to32,
-                                            getWReg(ws))));
-                           break;
+      case 0x1A:  /* DIV */
+         switch (sa & 0x3) {
+            case 0:
+               DIP("div r%u, r%u", rs, rt);
 
-                        case 1:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_V128to32,
-                                                 getWReg(ws)))));
-                           break;
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        case 2:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+               if (mode64) {
+                  t2 = newTemp(Ity_I64);
 
-                        case 3:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+                  assign(t2, binop(Iop_DivModS32to32,
+                                   mkNarrowTo32(ty, getIReg(rs)),
+                                   mkNarrowTo32(ty, getIReg(rt))));
 
-                        case 4:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+               } else {
+                  t1 = newTemp(Ity_I64);
 
-                        case 5:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+                  assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
 
-                        case 6:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+                  putHI(unop(Iop_64HIto32, mkexpr(t1)));
+                  putLO(unop(Iop_64to32, mkexpr(t1)));
+               }
 
-                        case 7:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128to64,
-                                                      getWReg(ws))))));
-                           break;
+               break;
 
-                        case 8:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+            case 2:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("div r%u, r%u, r%u", rs, rt, rd);
 
-                        case 9:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Sto64,
+                                      binop(Iop_DivS32,
+                                            unop(Iop_64to32, getIReg(rs)),
+                                            unop(Iop_64to32, getIReg(rt)))));
+                  } else {
+                     putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        case 10:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+               break;
 
-                        case 11:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64to32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+            case 3:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("mod r%u, r%u, r%u", rs, rt, rd);
 
-                        case 12:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Sto64,
+                                      unop(Iop_64HIto32,
+                                           binop(Iop_DivModS32to32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     t1 = newTemp(Ity_I64);
 
-                        case 13:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32to16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+                     assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
+                     putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        case 14:
-                           assign(t1,
-                                  unop(Iop_16to8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
+               break;
+         }
 
-                        case 15:
-                           assign(t1,
-                                  unop(Iop_16HIto8,
-                                       unop(Iop_32HIto16,
-                                            unop(Iop_64HIto32,
-                                                 unop(Iop_V128HIto64,
-                                                      getWReg(ws))))));
-                           break;
-                     }
+         break;
 
-                     putIReg(wd,
-                             unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
-                                  mkexpr(t1)));
-                     break;
+      case 0x1B:  /* DIVU */
+         switch (sa & 0x3) {
+            case 0:
+               DIP("divu r%u, r%u", rs, rt);
 
-                  case 0x20: /* COPY_S.H */
-                     DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
-                     t1 = newTemp(Ity_I16);
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                     switch (n) {
-                        case 0:
-                           assign(t1,
-                                  unop(Iop_32to16,
-                                       unop(Iop_64to32,
-                                            unop(Iop_V128to64,
-                                                 getWReg(ws)))));
-                           break;
+               if (mode64) {
+                  t1 = newTemp(Ity_I64);
 
-                        case 1:
-                           assign(t1,
-                                  unop(Iop_32HIto16,
-                                       unop(Iop_64to32,
-                                            unop(Iop_V128to64,
-                                                 getWReg(ws)))));
-                           break;
+                  assign(t1, binop(Iop_DivModU32to32,
+                                   mkNarrowTo32(ty, getIReg(rs)),
+                                   mkNarrowTo32(ty, getIReg(rt))));
 
-                        case 2:
-                           assign(t1,
-                                  unop(Iop_32to16,
-                                       unop(Iop_64HIto32,
-                                            unop(Iop_V128to64,
-                                                 getWReg(ws)))));
-                           break;
+                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
+                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
+               } else {
+                  t1 = newTemp(Ity_I64);
 
-                        case 3:
-                           assign(t1,
-                                  unop(Iop_32HIto16,
-                                       unop(Iop_64HIto32,
-                                            unop(Iop_V128to64,
-                                                 getWReg(ws)))));
-                           break;
+                  assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
+                  putHI(unop(Iop_64HIto32, mkexpr(t1)));
+                  putLO(unop(Iop_64to32, mkexpr(t1)));
+               }
 
-                        case 4:
-                           assign(t1,
-                                  unop(Iop_32to16,
-                                       unop(Iop_64to32,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(ws)))));
-                           break;
+               break;
 
-                        case 5:
-                           assign(t1,
-                                  unop(Iop_32HIto16,
-                                       unop(Iop_64to32,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(ws)))));
-                           break;
+            case 2:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("divu r%u, r%u, r%u", rs, rt, rd);
 
-                        case 6:
-                           assign(t1,
-                                  unop(Iop_32to16,
-                                       unop(Iop_64HIto32,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(ws)))));
-                           break;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Sto64,
+                                      binop(Iop_DivU32,
+                                            unop(Iop_64to32, getIReg(rs)),
+                                            unop(Iop_64to32, getIReg(rt)))));
+                  } else {
+                     putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
+                  }
 
-                        case 7:
-                           assign(t1,
-                                  unop(Iop_32HIto16,
-                                       unop(Iop_64HIto32,
-                                            unop(Iop_V128HIto64,
-                                                 getWReg(ws)))));
-                           break;
-                     }
+                  break;
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                     putIReg(wd,
-                             unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
-                                  mkexpr(t1)));
-                     break;
+               break;
 
-                  case 0x30: /* COPY_S.W */
-                     DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
+            case 3:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("modu r%u, r%u, r%u", rs, rt, rd);
 
-                     switch (n) {
-                        case 0:
-                           putIReg(wd,
-                                   mkWidenFrom32(ty,
-                                                 unop(Iop_V128to32,
-                                                      getWReg(ws)),
-                                                 True));
-                           break;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Uto64,
+                                      unop(Iop_64HIto32,
+                                           binop(Iop_DivModU32to32,
+                                                 unop(Iop_64to32, getIReg(rs)),
+                                                 unop(Iop_64to32, getIReg(rt))))));
+                  } else {
+                     t1 = newTemp(Ity_I64);
+
+                     assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
+                     putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        case 1:
-                           t2 = newTemp(Ity_I64);
-                           assign(t2,
-                                  unop(Iop_V128to64, getWReg(ws)));
-                           putIReg(wd,
-                                   mkWidenFrom32(ty,
-                                                 unop(Iop_64HIto32,
-                                                      mkexpr(t2)),
-                                                 True));
-                           break;
+               break;
+         }
 
-                        case 2:
-                           t2 = newTemp(Ity_I64);
-                           assign(t2,
-                                  unop(Iop_V128HIto64,
-                                       getWReg(ws)));
-                           putIReg(wd,
-                                   mkWidenFrom32(ty,
-                                                 unop(Iop_64to32,
-                                                      mkexpr(t2)),
-                                                 True));
-                           break;
+         break;
 
-                        case 3:
-                           t2 = newTemp(Ity_I64);
-                           assign(t2,
-                                  unop(Iop_V128HIto64,
-                                       getWReg(ws)));
-                           putIReg(wd,
-                                   mkWidenFrom32(ty,
-                                                 unop(Iop_64HIto32,
-                                                      mkexpr(t2)),
-                                                 True));
-                           break;
+      case 0x1C:  /* Doubleword Multiply - DMULT; MIPS64 */
+         switch (sa) {
+            case 0:
+               DIP("dmult r%u, r%u", rs, rt);
 
-                        default:
-                           break;
-                     }
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                     break;
+               t0 = newTemp(Ity_I128);
 
-                  case 0x38: /* COPY_S.D */
-                     if (mode64) {
-                        DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
+               assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
 
-                        switch (n) {
-                           case 0:
-                              putIReg(wd,
-                                      unop(Iop_V128to64,
-                                           getWReg(ws)));
-                              break;
+               putHI(unop(Iop_128HIto64, mkexpr(t0)));
+               putLO(unop(Iop_128to64, mkexpr(t0)));
+               break;
 
-                           case 1:
-                              putIReg(wd,
-                                      unop(Iop_V128HIto64,
-                                           getWReg(ws)));
-                              break;
-                        }
-                     } else {
-                        return -2;
-                     }
+            case 2: /* DMUL */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmul r%u, r%u, r%u", rd, rs, rt);
+                  putIReg(rd, unop(Iop_128to64,
+                                   binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                     break;
+               break;
 
-                  default:
-                     return -1;
+            case 3: /* DMUH */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
+                  putIReg(rd, unop(Iop_128HIto64,
+                                   binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
                }
 
                break;
+         }
 
-            case 0x03: { /* COPY_U.df */
-                  switch (df) {
-                     case 0x00: /* COPY_U.B */
-                        DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
-                        t1 = newTemp(Ity_I8);
+         break;
 
-                        switch (n) {
-                           case 0:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+      case 0x1D:  /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
+         switch (sa) {
+            case 0:
+               DIP("dmultu r%u, r%u", rs, rt);
 
-                           case 1:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                           case 2:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+               t0 = newTemp(Ity_I128);
 
-                           case 3:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+               assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
 
-                           case 4:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+               putHI(unop(Iop_128HIto64, mkexpr(t0)));
+               putLO(unop(Iop_128to64, mkexpr(t0)));
+               break;
 
-                           case 5:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+            case 2: /* DMULU */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
+                  putIReg(rd, unop(Iop_128to64,
+                                   binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                           case 6:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+               break;
 
-                           case 7:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128to64,
-                                                         getWReg(ws))))));
-                              break;
+            case 3: /* DMUHU */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
+                  putIReg(rd, unop(Iop_128HIto64,
+                                   binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                           case 8:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+               break;
+         }
 
-                           case 9:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+         break;
 
-                           case 10:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+      case 0x1E:  /* Doubleword Divide DDIV; MIPS64 */
+         switch (sa) {
+            case 0:
+               DIP("ddiv r%u, r%u", rs, rt);
 
-                           case 11:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64to32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                           case 12:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+               t1 = newTemp(Ity_I128);
 
-                           case 13:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32to16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+               assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
 
-                           case 14:
-                              assign(t1,
-                                     unop(Iop_16to8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
+               putHI(unop(Iop_128HIto64, mkexpr(t1)));
+               putLO(unop(Iop_128to64, mkexpr(t1)));
+               break;
 
-                           case 15:
-                              assign(t1,
-                                     unop(Iop_16HIto8,
-                                          unop(Iop_32HIto16,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_V128HIto64,
-                                                         getWReg(ws))))));
-                              break;
-                        }
+            case 2: /* DDIV r6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
+                  putIReg(rd, unop(Iop_128to64,
+                                   binop(Iop_DivModS64to64,
+                                         getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        putIReg(wd,
-                                unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
-                                     mkexpr(t1)));
-                        break;
+               break;
 
-                     case 0x20: /* COPY_U.H */
-                        DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
-                        t1 = newTemp(Ity_I16);
+            case 3: /* DMOD r6 */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmod r%u, r%u, r%u", rs, rt, rd);
+                  t2 = newTemp(Ity_I128);
+                  assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
+                  putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        switch (n) {
-                           case 0:
-                              assign(t1,
-                                     unop(Iop_32to16,
-                                          unop(Iop_64to32,
-                                               unop(Iop_V128to64,
-                                                    getWReg(ws)))));
-                              break;
+               break;
+         }
 
-                           case 1:
-                              assign(t1,
-                                     unop(Iop_32HIto16,
-                                          unop(Iop_64to32,
-                                               unop(Iop_V128to64,
-                                                    getWReg(ws)))));
-                              break;
+         break;
 
-                           case 2:
-                              assign(t1,
-                                     unop(Iop_32to16,
-                                          unop(Iop_64HIto32,
-                                               unop(Iop_V128to64,
-                                                    getWReg(ws)))));
-                              break;
+      case 0x1F:  /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
+         switch (sa) {
+            case 0:
+               DIP("ddivu r%u, r%u", rs, rt);
 
-                           case 3:
-                              assign(t1,
-                                     unop(Iop_32HIto16,
-                                          unop(Iop_64HIto32,
-                                               unop(Iop_V128to64,
-                                                    getWReg(ws)))));
-                              break;
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+                     !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                           case 4:
-                              assign(t1,
-                                     unop(Iop_32to16,
-                                          unop(Iop_64to32,
-                                               unop(Iop_V128HIto64,
-                                                    getWReg(ws)))));
-                              break;
+               t1 = newTemp(Ity_I128);
 
-                           case 5:
-                              assign(t1,
-                                     unop(Iop_32HIto16,
-                                          unop(Iop_64to32,
-                                               unop(Iop_V128HIto64,
-                                                    getWReg(ws)))));
-                              break;
+               assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
 
-                           case 6:
-                              assign(t1,
-                                     unop(Iop_32to16,
-                                          unop(Iop_64HIto32,
-                                               unop(Iop_V128HIto64,
-                                                    getWReg(ws)))));
-                              break;
+               putHI(unop(Iop_128HIto64, mkexpr(t1)));
+               putLO(unop(Iop_128to64, mkexpr(t1)));
+               break;
 
-                           case 7:
-                              assign(t1,
-                                     unop(Iop_32HIto16,
-                                          unop(Iop_64HIto32,
-                                               unop(Iop_V128HIto64,
-                                                    getWReg(ws)))));
-                              break;
-                        }
+            case 2:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
+                  putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
+                                                      getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        putIReg(wd,
-                                unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
-                                     mkexpr(t1)));
-                        break;
+               break;
 
-                     case 0x30: /* COPY_U.W */
-                        DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
+            case 3:
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
+                  putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
+                                                        getIReg(rs), getIReg(rt))));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        switch (n) {
-                           case 0:
-                              putIReg(wd,
-                                      mkWidenFrom32(ty,
-                                                    unop(Iop_V128to32,
-                                                         getWReg(ws)),
-                                                    False));
-                              break;
+               break;
+         }
 
-                           case 1:
-                              t2 = newTemp(Ity_I64);
-                              assign(t2,
-                                     unop(Iop_V128to64,
-                                          getWReg(ws)));
-                              putIReg(wd,
-                                      mkWidenFrom32(ty,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t2)),
-                                                    False));
-                              break;
+         break;
 
-                           case 2:
-                              t2 = newTemp(Ity_I64);
-                              assign(t2,
-                                     unop(Iop_V128HIto64,
-                                          getWReg(ws)));
-                              putIReg(wd,
-                                      mkWidenFrom32(ty,
-                                                    unop(Iop_64to32,
-                                                         mkexpr(t2)),
-                                                    False));
-                              break;
+      case 0x20: {  /* ADD */
+         DIP("add r%u, r%u, r%u", rd, rs, rt);
+         IRTemp tmpRs32 = newTemp(Ity_I32);
+         IRTemp tmpRt32 = newTemp(Ity_I32);
 
-                           case 3:
-                              t2 = newTemp(Ity_I64);
-                              assign(t2,
-                                     unop(Iop_V128HIto64,
-                                          getWReg(ws)));
-                              putIReg(wd,
-                                      mkWidenFrom32(ty,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t2)),
-                                                    False));
-                              break;
+         assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+         assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
 
-                           default:
-                              break;
-                        }
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         /* dst = src0 + src1
+               if (sign(src0 ) != sign(src1 ))
+               goto no overflow;
+               if (sign(dst) == sign(src0 ))
+               goto no overflow;
+               we have overflow! */
 
-                        break;
+         assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+         assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+         assign(t2, unop(Iop_1Uto32,
+                         binop(Iop_CmpEQ32,
+                               binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+                               mkU32(0x80000000))));
 
-                     default:
-                        return -1;
-                  }
+         assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+         assign(t4, unop(Iop_1Uto32,
+                         binop(Iop_CmpNE32,
+                               binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+                               mkU32(0x80000000))));
 
-                  break;
-               }
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
+                                binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+                                mkU32(0)),
+                          Ijk_SigFPE_IntOvf,
+                          mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+                          IRConst_U32(guest_PC_curr_instr + 4),
+                          OFFB_PC));
 
-            case 0x04: { /* INSERT.df */
-                  t5 = newTemp(Ity_I64);
-                  UInt hi = 1;
-                  ULong mask;
-                  IRTemp *src, *dst;
-                  assign(t5, mode64 ? getIReg(ws) :
-                         unop(Iop_32Uto64, getIReg(ws)));
-
-                  if (df == 0x38) { /* INSERT.D */
-                     if (mode64) {
-                        DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
+         putIReg(rd,  mkWidenFrom32(ty, mkexpr(t0), True));
+         break;
+      }
 
-                        if (n == 0) {
-                           putWReg(wd,
-                                   binop(Iop_64HLtoV128,
-                                         unop(Iop_V128HIto64,
-                                              getWReg(wd)),
-                                         mkexpr(t5)));
-                        } else {
-                           putWReg(wd,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(t5),
-                                         unop(Iop_V128to64,
-                                              getWReg(wd))));
-                        }
+      case 0x21:  /* ADDU */
+         DIP("addu r%u, r%u, r%u", rd, rs, rt);
 
-                        break;
-                     } else {
-                        return -2;
-                     }
-                  } else {
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1, unop(Iop_V128to64, getWReg(wd)));
-                     assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
-                  }
+         if (mode64) {
+            ALU_PATTERN64(Iop_Add32);
+         } else {
+            ALU_PATTERN(Iop_Add32);
+         }
 
-                  switch (df) {
-                     case 0x00: /* INSERT.B */
-                        DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
+         break;
 
-                        if (n >= 8) {
-                           n -= 8;
-                        } else {
-                           hi = 0;
-                        }
+      case 0x22: {  /* SUB */
+         DIP("sub r%u, r%u, r%u", rd, rs, rt);
+         IRTemp tmpRs32 = newTemp(Ity_I32);
+         IRTemp tmpRt32 = newTemp(Ity_I32);
 
-                        n <<= 3;
-                        mask = 0xFFull;
-                        break;
+         assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+         assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         /* dst = src0 + (-1 * src1)
+               if(sign(src0 ) != sign((-1 * src1) ))
+               goto no overflow;
+               if(sign(dst) == sign(src0 ))
+               goto no overflow;
+               we have overflow! */
 
-                     case 0x20: /* INSERT.H */
-                        DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
+         assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
+         assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
+         assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
+         assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
+                                           mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
 
-                        if (n >= 4) {
-                           n -= 4;
-                        } else {
-                           hi = 0;
-                        }
+         assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+         assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
+                                           mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
 
-                        n <<= 4;
-                        mask = 0xFFFFull;
-                        break;
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
+                                mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
+                          mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+                          IRConst_U32(guest_PC_curr_instr + 4),
+                          OFFB_PC));
 
-                     case 0x30: /* INSERT.W */
-                        DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
+         putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
+         break;
+      }
 
-                        if (n >= 2) {
-                           n -= 2;
-                        } else {
-                           hi = 0;
-                        }
+      case 0x23:  /* SUBU */
+         DIP("subu r%u, r%u, r%u", rd, rs, rt);
 
-                        n <<= 5;
-                        mask = 0xFFFFFFFFull;
-                        break;
+         if (mode64) {
+            ALU_PATTERN64(Iop_Sub32);
+         } else {
+            ALU_PATTERN(Iop_Sub32);
+         }
 
-                     default:
-                        return -1;
-                  }
+         break;
 
-                  if (hi) {
-                     t4 = newTemp(Ity_I64);
-                     src = &t2;
-                     dst = &t4;
-                     t3 = t1;
-                  } else {
-                     t3 = newTemp(Ity_I64);
-                     src = &t1;
-                     dst = &t3;
-                     t4 = t2;
-                  }
+      case 0x24:  /* AND */
+         DIP("and r%u, r%u, r%u", rd, rs, rt);
 
-                  mask <<= n;
-                  assign(*dst,
-                      binop(Iop_Or64,
-                            binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
-                            binop(Iop_And64,
-                                  binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
-                                  mkU64(mask))));
-                  putWReg(wd,
-                          binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
-                  break;
-               }
+         if (mode64) {
+            ALU_PATTERN(Iop_And64);
+         } else {
+            ALU_PATTERN(Iop_And32);
+         }
 
-            case 0x05: { /* INSVE.df */
-                  switch (df) {
-                     case 0x00: { /* INSVE.B */
-                           DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
-                           t1 = newTemp(Ity_V128);
-                           t2 = newTemp(Ity_V128);
-                           assign(t1, getWReg(wd));
-                           assign(t2, getWReg(ws));
-                           Int i;
-                           IRTemp tmp[16];
-
-                           for (i = 0; i < 16; i++) {
-                              tmp[i] = newTemp(Ity_I8);
-
-                              if (n == i)
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem8x16,
-                                              mkexpr(t2), mkU8(0x0)));
-                              else
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem8x16,
-                                              mkexpr(t1), mkU8(i)));
-                           }
+         break;
 
-                           putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[15]),
-                                                     mkexpr(tmp[14])),
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[13]),
-                                                     mkexpr(tmp[12]))),
-                                         binop(Iop_16HLto32,
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[11]),
-                                                     mkexpr(tmp[10])),
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[9]),
-                                                     mkexpr(tmp[8])))),
-                                   binop(Iop_32HLto64,
-                                         binop(Iop_16HLto32,
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[7]),
-                                                     mkexpr(tmp[6])),
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[5]),
-                                                     mkexpr(tmp[4]))),
-                                         binop(Iop_16HLto32,
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[3]),
-                                                     mkexpr(tmp[2])),
-                                               binop(Iop_8HLto16,
-                                                     mkexpr(tmp[1]),
-                                                     mkexpr(tmp[0]))))));
-                           break;
-                        }
+      case 0x25:  /* OR */
+         DIP("or r%u, r%u, r%u", rd, rs, rt);
 
-                     case 0x20: { /* INSVE.H */
-                           DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
-                           t1 = newTemp(Ity_V128);
-                           t2 = newTemp(Ity_V128);
-                           assign(t1, getWReg(wd));
-                           assign(t2, getWReg(ws));
-                           Int i;
-                           IRTemp tmp[8];
+         if (mode64) {
+            ALU_PATTERN(Iop_Or64);
+         } else {
+            ALU_PATTERN(Iop_Or32);
+         }
 
-                           for (i = 0; i < 8; i++) {
-                              tmp[i] = newTemp(Ity_I16);
+         break;
 
-                              if (n == i)
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem16x8,
-                                              mkexpr(t2), mkU8(0x0)));
-                              else
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem16x8,
-                                              mkexpr(t1), mkU8(i)));
-                           }
+      case 0x26:  /* XOR */
+         DIP("xor r%u, r%u, r%u", rd, rs, rt);
 
-                           putWReg(wd,
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               binop(Iop_16HLto32,
-                                                     mkexpr(tmp[7]),
-                                                     mkexpr(tmp[6])),
-                                               binop(Iop_16HLto32,
-                                                     mkexpr(tmp[5]),
-                                                     mkexpr(tmp[4]))),
-                                         binop(Iop_32HLto64,
-                                               binop(Iop_16HLto32,
-                                                     mkexpr(tmp[3]),
-                                                     mkexpr(tmp[2])),
-                                               binop(Iop_16HLto32,
-                                                     mkexpr(tmp[1]),
-                                                     mkexpr(tmp[0])))));
-                           break;
-                        }
+         if (mode64) {
+            ALU_PATTERN(Iop_Xor64);
+         } else {
+            ALU_PATTERN(Iop_Xor32);
+         }
 
-                     case 0x30: { /* INSVE.W */
-                           DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
-                           t1 = newTemp(Ity_V128);
-                           t2 = newTemp(Ity_V128);
-                           assign(t1, getWReg(wd));
-                           assign(t2, getWReg(ws));
-                           Int i;
-                           IRTemp tmp[4];
+         break;
 
-                           for (i = 0; i < 4; i++) {
-                              tmp[i] = newTemp(Ity_I32);
+      case 0x27:  /* NOR */
+         DIP("nor r%u, r%u, r%u", rd, rs, rt);
 
-                              if (n == i)
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem32x4,
-                                              mkexpr(t2), mkU8(0x0)));
-                              else
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem32x4,
-                                              mkexpr(t1), mkU8(i)));
-                           }
+         if (mode64)
+            putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
+                                              getIReg(rt))));
+         else
+            putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
+                                              getIReg(rt))));
 
-                           putWReg(wd,
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0]))));
-                           break;
-                        }
+         break;
 
-                     case 0x38: { /* INSVE.D */
-                           DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
-                           t1 = newTemp(Ity_V128);
-                           t2 = newTemp(Ity_V128);
-                           assign(t1, getWReg(wd));
-                           assign(t2, getWReg(ws));
-                           Int i;
-                           IRTemp tmp[2];
+      case 0x2A:  /* SLT */
+         DIP("slt r%u, r%u, r%u", rd, rs, rt);
 
-                           for (i = 0; i < 2; i++) {
-                              tmp[i] = newTemp(Ity_I64);
+         if (mode64)
+            putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
+                                               getIReg(rt))));
+         else
+            putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+                                               getIReg(rt))));
 
-                              if (n == i)
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem64x2,
-                                              mkexpr(t2), mkU8(0x0)));
-                              else
-                                 assign(tmp[i],
-                                        binop(Iop_GetElem64x2,
-                                              mkexpr(t1), mkU8(i)));
-                           }
+         break;
 
-                           putWReg(wd,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]), mkexpr(tmp[0])));
-                           break;
-                        }
-                  }
+      case 0x2B:  /* SLTU */
+         DIP("sltu r%u, r%u, r%u", rd, rs, rt);
 
-                  break;
-               }
+         if (mode64)
+            putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
+                                               getIReg(rt))));
+         else
+            putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+                                               getIReg(rt))));
 
-            default:
-               return -1;
-      }
-   }
-   return 0;
-}
+         break;
 
-static Int msa_VEC(UInt cins, UChar wd, UChar ws) { /* VEC */
-   IRTemp t1, t2, t3;
-   UShort operation;
-   UChar wt;
+      case 0x2C: {  /* Doubleword Add - DADD; MIPS64 */
+         DIP("dadd r%u, r%u, r%u", rd, rs, rt);
+         IRTemp tmpRs64 = newTemp(Ity_I64);
+         IRTemp tmpRt64 = newTemp(Ity_I64);
 
-   vassert((cins & 0x03000000) == 0);
+         assign(tmpRs64, getIReg(rs));
+         assign(tmpRt64, getIReg(rt));
 
-   operation = (cins & 0x03E00000) >> 21;
-   wt = (cins & 0x001F0000) >> 16;
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I64);
+         /* dst = src0 + src1
+               if(sign(src0 ) != sign(src1 ))
+               goto no overflow;
+               if(sign(dst) == sign(src0 ))
+               goto no overflow;
+               we have overflow! */
 
-   switch (operation) {
-      case 0x00: { /* AND.V */
-            DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
-            assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+         assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
+         assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
+         assign(t2, unop(Iop_1Uto64,
+                         binop(Iop_CmpEQ64,
+                               binop(Iop_And64, mkexpr(t1),
+                                     mkU64(0x8000000000000000ULL)),
+                               mkU64(0x8000000000000000ULL))));
 
-      case 0x01: { /* OR.V */
-            DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+         assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+         assign(t4, unop(Iop_1Uto64,
+                         binop(Iop_CmpNE64,
+                               binop(Iop_And64, mkexpr(t3),
+                                     mkU64(0x8000000000000000ULL)),
+                               mkU64(0x8000000000000000ULL))));
 
-      case 0x02: { /* NOR.V */
-            DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
-            assign(t3,
-                   unop(Iop_NotV128,
-                        binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
+                                binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
+                                mkU64(0)),
+                          Ijk_SigFPE_IntOvf,
+                          IRConst_U64(guest_PC_curr_instr + 4),
+                          OFFB_PC));
 
-      case 0x03: { /* XOR.V */
-            DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            assign(t2, getWReg(wt));
-            assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+         putIReg(rd,  mkexpr(t0));
+         break;
+      }
 
-      case 0x04: { /* BMNZ  (ws AND wt) OR (wd AND NOT wt) */
-            DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1,
-                   binop(Iop_AndV128,
-                         getWReg(ws), getWReg(wt)));
-            assign(t2,
-                   binop(Iop_AndV128,
-                         getWReg(wd),
-                         unop(Iop_NotV128, getWReg(wt))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+      case 0x2D:  /* Doubleword Add Unsigned - DADDU; MIPS64 */
+         DIP("daddu r%u, r%u, r%u", rd, rs, rt);
+         ALU_PATTERN(Iop_Add64);
+         break;
 
-      case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
-            DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1,
-                   binop(Iop_AndV128,
-                         getWReg(wd), getWReg(wt)));
-            assign(t2,
-                   binop(Iop_AndV128,
-                         getWReg(ws),
-                         unop(Iop_NotV128, getWReg(wt))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+      case 0x2E: {  /* Doubleword Subtract - DSUB; MIPS64 */
+         DIP("dsub r%u, r%u, r%u", rd, rs, rt);
+         IRTemp tmpRs64 = newTemp(Ity_I64);
+         IRTemp tmpRt64 = newTemp(Ity_I64);
 
-      case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
-            DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            assign(t1,
-                   binop(Iop_AndV128,
-                         getWReg(wd), getWReg(wt)));
-            assign(t2,
-                   binop(Iop_AndV128,
-                         getWReg(ws),
-                         unop(Iop_NotV128, getWReg(wd))));
-            assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
-            putWReg(wd, mkexpr(t3));
-            break;
-         }
+         assign(tmpRs64, getIReg(rs));
+         assign(tmpRt64, getIReg(rt));
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         /* dst = src0 + (-1 * src1)
+               if(sign(src0 ) != sign((-1 * src1) ))
+               goto no overflow;
+               if(sign(dst) == sign(src0 ))
+               goto no overflow;
+               we have overflow! */
 
-      default:
-         return -1;
-   }
+         assign(t5, binop(Iop_Mul64,
+                          mkexpr(tmpRt64),
+                          mkU64(0xffffffffffffffffULL)));
+         assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
+         assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
+         assign(t2, unop(Iop_1Sto64,
+                         binop(Iop_CmpEQ64,
+                               binop(Iop_And64,
+                                     mkexpr(t1),
+                                     mkU64(0x8000000000000000ULL)),
+                               mkU64(0x8000000000000000ULL))));
 
-   return 0;
-}
+         assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+         assign(t4, unop(Iop_1Sto64,
+                         binop(Iop_CmpNE64,
+                               binop(Iop_And64,
+                                     mkexpr(t3),
+                                     mkU64(0x8000000000000000ULL)),
+                               mkU64(0x8000000000000000ULL))));
 
-static Int msa_2R(UInt cins, UChar wd, UChar ws) { /* 2R */
-   IRTemp t1, t2, t3, t4;
-   IRType ty;
-   UShort operation;
-   UChar df;
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
+                                mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
+                          IRConst_U64(guest_PC_curr_instr + 4),
+                          OFFB_PC));
 
-   vassert((cins & 0x00200000) == 0);
+         putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
+         break;
+      }
 
-   operation = (cins & 0x03FC0000) >> 18;
-   df = (cins & 0x00030000) >> 16;
-   ty = mode64 ? Ity_I64 : Ity_I32;
+      case 0x2F:  /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
+         DIP("dsub r%u, r%u,r%u", rd, rt, rt);
+         ALU_PATTERN(Iop_Sub64);
+         break;
 
-   switch (operation) {
-      case 0xC0: { /* FILL.df */
-            t1 = newTemp(Ity_I64);
+      case 0x30: {  /* TGE */
+         DIP("tge r%u, r%u %u", rs, rt, trap_code);
 
-            switch (df) {
-               case 0x00: /* FILL.B */
-                  DIP("FILL.B w%d, r%d", wd, ws);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I16);
-                  t4 = newTemp(Ity_I8);
-                  assign(t4, mkNarrowTo8(ty, getIReg(ws)));
-                  assign(t3,
-                         binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
-                  assign(t2,
-                         binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
-                  assign(t1,
-                         binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
-                  break;
+         if (mode64) {
+            if (trap_code == 7)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntDiv,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else if (trap_code == 6)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntOvf,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigTRAP,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntDiv,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else if (trap_code == 6)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntOvf,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32S,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigTRAP,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+         }
 
-               case 0x01: /* FILL.H */
-                  DIP("FILL.H w%d, r%d", wd, ws);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I16);
-                  assign(t3, mkNarrowTo16(ty, getIReg(ws)));
-                  assign(t2,
-                         binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
-                  assign(t1,
-                         binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
-                  break;
+         break;
+      }
 
-               case 0x02: /* FILL.W */
-                  DIP("FILL.W w%d, r%d", wd, ws);
-                  t2 = newTemp(Ity_I32);
-                  assign(t2, mkNarrowTo32(ty, getIReg(ws)));
-                  assign(t1,
-                         binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
-                  break;
+      case 0x31: {  /* TGEU */
+         DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
 
-               case 0x03: /* FILL.D */
-                  if (mode64) {
-                     DIP("FILL.W w%d, r%d", wd, ws);
-                     t2 = newTemp(Ity_I32);
-                     assign(t1, getIReg(ws));
-                  } else {
-                     return -2;
-                  }
+         if (mode64) {
+            if (trap_code == 7)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntDiv,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else if (trap_code == 6)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntOvf,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT64U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigTRAP,
+                                  IRConst_U64(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntDiv,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else if (trap_code == 6)
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigFPE_IntOvf,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+            else
+               stmt (IRStmt_Exit (unop (Iop_Not1,
+                                        binop (Iop_CmpLT32U,
+                                               getIReg (rs),
+                                               getIReg (rt))),
+                                  Ijk_SigTRAP,
+                                  IRConst_U32(guest_PC_curr_instr + 4),
+                                  OFFB_PC));
+         }
 
-                  break;
+         break;
+      }
 
-               default:
-                  return -1;
-            }
+      case 0x32: {  /* TLT */
+         DIP("tlt r%u, r%u %u", rs, rt, trap_code);
 
-            putWReg(wd,
-                    binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
-            break;
+         if (mode64) {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
          }
 
-      case 0xC1: { /* PCNT.df */
-            switch (df) {
-               case 0x00: /* PCNT.B */
-                  DIP("PCNT.B w%d, r%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Cnt8x16, getWReg(ws)));
-                  break;
+         break;
+      }
 
-               case 0x01: /* PCNT.H */
-                  DIP("PCNT.H w%d, r%d", wd, ws);
-                  t1 = newTemp(Ity_V128);
-                  t2 = newTemp(Ity_V128);
-                  assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
-                  assign(t2,
-                      binop(Iop_Add16x8,
-                         binop(Iop_AndV128,
-                               mkexpr(t1),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN16x8,
-                                     mkexpr(t1), mkU8(8)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL)))));
-                  putWReg(wd, mkexpr(t2));
-                  break;
+      case 0x33: {  /* TLTU */
+         DIP("tltu r%u, r%u %u", rs, rt, trap_code);
 
-               case 0x02: /* PCNT.W */
-                  DIP("PCNT.W w%d, r%d", wd, ws);
-                  t1 = newTemp(Ity_V128);
-                  t2 = newTemp(Ity_V128);
-                  t3 = newTemp(Ity_V128);
-                  assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
-                  assign(t2,
-                      binop(Iop_Add32x4,
-                         binop(Iop_AndV128,
-                               mkexpr(t1),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN32x4,
-                                     mkexpr(t1), mkU8(8)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL)))));
-                  assign(t3,
-                      binop(Iop_Add32x4,
-                         binop(Iop_AndV128,
-                               mkexpr(t2),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x0000FFFF0000FFFFULL),
-                                     mkU64(0x0000FFFF0000FFFFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN32x4,
-                                     mkexpr(t2), mkU8(16)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x0000FFFF0000FFFFULL),
-                                     mkU64(0x0000FFFF0000FFFFULL)))));
-                  putWReg(wd, mkexpr(t3));
-                  break;
+         if (mode64) {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+                                      getIReg (rt)), Ijk_SigTRAP,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         }
 
-               case 0x03: /* PCNT.D */
-                  DIP("PCNT.D w%d, r%d", wd, ws);
-                  t1 = newTemp(Ity_V128);
-                  t2 = newTemp(Ity_V128);
-                  t3 = newTemp(Ity_V128);
-                  t4 = newTemp(Ity_V128);;
-                  assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
-                  assign(t2,
-                      binop(Iop_Add64x2,
-                         binop(Iop_AndV128,
-                               mkexpr(t1),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN64x2,
-                                     mkexpr(t1), mkU8(8)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00FF00FF00FF00FFULL),
-                                     mkU64(0x00FF00FF00FF00FFULL)))));
-                  assign(t3,
-                      binop(Iop_Add64x2,
-                         binop(Iop_AndV128,
-                               mkexpr(t2),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x0000FFFF0000FFFFULL),
-                                     mkU64(0x0000FFFF0000FFFFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN64x2,
-                                     mkexpr(t2), mkU8(16)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x0000FFFF0000FFFFULL),
-                                     mkU64(0x0000FFFF0000FFFFULL)))));
-                  assign(t4,
-                      binop(Iop_Add64x2,
-                         binop(Iop_AndV128,
-                               mkexpr(t3),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00000000FFFFFFFFULL),
-                                     mkU64(0x00000000FFFFFFFFULL))),
-                         binop(Iop_AndV128,
-                               binop(Iop_ShrN64x2,
-                                     mkexpr(t3), mkU8(32)),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x00000000FFFFFFFFULL),
-                                     mkU64(0x00000000FFFFFFFFULL)))));
-                  putWReg(wd, mkexpr(t4));
-                  break;
+         break;
+      }
 
-               default:
-                  return -1;
-            }
+      case 0x34: {  /* TEQ */
+         DIP("teq r%u, r%u, %u", rs, rt, trap_code);
 
-            break;
+         if (mode64) {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
          }
 
-      case 0xC2: { /* NLOC.df */
-            switch (df) {
-               case 0x00: /* NLOC.B */
-                  DIP("NLOC.B w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Cls8x16, getWReg(ws)));
-                  break;
-
-               case 0x01: /* NLOC.H */
-                  DIP("NLOC.H w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Cls16x8, getWReg(ws)));
-                  break;
-
-               case 0x02: /* NLOC.W */
-                  DIP("NLOC.W w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Cls32x4, getWReg(ws)));
-                  break;
+         break;
+      }
 
-               case 0x03: /* NLOC.D */
-                  DIP("NLOC.D w%d, w%d", wd, ws);
-                  t1 = newTemp(Ity_V128);
-                  assign(t1, unop(Iop_NotV128, getWReg(ws)));
-                  putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
-                  break;
+      case 0x35: {   /* SELEQZ */
+         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
 
-               default:
-                  return -1;
+            if (mode64) {
+               putIReg(rd, binop(Iop_And64,
+                                 unop(Iop_Not64,
+                                      unop(Iop_CmpwNEZ64, getIReg(rt))),
+                                 getIReg(rs)));
+            } else {
+               putIReg(rd, binop(Iop_And32,
+                                 unop(Iop_Not32,
+                                      unop(Iop_CmpwNEZ32, getIReg(rt))),
+                                 getIReg(rs)));
             }
-
-            break;
+         } else {
+            ILLEGAL_INSTRUCTON;
          }
 
-      case 0xC3: { /* NLZC.df */
-            switch (df) {
-               case 0x00: /* NLZC.B */
-                  DIP("NLZC.W w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Clz8x16, getWReg(ws)));
-                  break;
+         break;
+      }
 
-               case 0x01: /* NLZC.H */
-                  DIP("NLZC.H w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Clz16x8, getWReg(ws)));
-                  break;
+      case 0x36: {  /* TNE */
+         DIP("tne r%u, r%u %u", rs, rt, trap_code);
 
-               case 0x02: /* NLZC.W */
-                  DIP("NLZC.W w%d, w%d", wd, ws);
-                  putWReg(wd,
-                          unop(Iop_Clz32x4, getWReg(ws)));
-                  break;
+         if (mode64) {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U64(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         } else {
+            if (trap_code == 7)
+               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else if (trap_code == 6)
+               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+            else
+               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+                                      getIReg(rt)), Ijk_SigTRAP,
+                                IRConst_U32(guest_PC_curr_instr + 4),
+                                OFFB_PC));
+         }
 
-               case 0x03: {/* NLZC.D */
-                     putWReg(wd,
-                             unop(Iop_Clz64x2, getWReg(ws)));
-                     break;
-                  }
+         break;
+      }
 
-               default:
-                  return -1;
+      case 0x37:  { /* SELNEZ */
+         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            DIP("selnez r%u, r%u, r%u", rd, rs, rt);
+
+            if (mode64) {
+               putIReg(rd, binop(Iop_And64,
+                                 unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
+            } else {
+               putIReg(rd, binop(Iop_And32,
+                                 unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
             }
+         } else {
+            ILLEGAL_INSTRUCTON;
+         }
+
+         break;
+      }
 
+      case 0x14:
+      case 0x16:
+      case 0x17:  /* DSLLV, DROTRV:DSRLV, DSRAV */
+      case 0x38:
+      case 0x3A:
+      case 0x3B:  /* DSLL, DROTL:DSRL, DSRA  */
+      case 0x3C:
+      case 0x3E:
+      case 0x3F:  /* DSLL32, DROTR32:DSRL32, DSRA32 */
+         if (dis_instr_shrt(cins))
             break;
-         }
+
+         return -1;
 
       default:
          return -1;
@@ -24504,1277 +18369,481 @@ static Int msa_2R(UInt cins, UChar wd, UChar ws) { /* 2R */
    return 0;
 }
 
-static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */
-   IRTemp t1, t2, t3, t4, t5;
-   UShort operation;
-   UChar df, wt;
-
-   operation = (cins & 0x03FE0000) >> 17;
-   df = (cins & 0x00010000) >> 16;
-   wt = (cins & 0x001F0000) >> 16;
+static UInt disInstr_MIPS_WRK_Special2(UInt cins, const VexArchInfo* archinfo,
+                                       const VexAbiInfo*  abiinfo, DisResult* dres,
+                                       IRStmt** bstmt, IRExpr** lastn,
+                                       Bool(*resteerOkFn) (/*opaque */void *,
+                                             Addr),
+                                       void*        callback_opaque)
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
+   UInt rs, rt, rd, function;
+   /* Additional variables for instruction fields in DSP ASE insructions */
+   UInt ac;
 
-   switch (operation) {
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
 
-      case 0x190: { /* FCLASS.df */
-            IRTemp t0 = newTemp(Ity_V128);
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            t4 = newTemp(Ity_V128);
-            t5 = newTemp(Ity_V128);
+   ac = get_acNo(cins);
 
-            switch (df) {
-               case 0x00: { /* FCLASS.W */
-                     DIP("FCLASS.W w%d, w%d", wd, ws);
-                     assign(t0,
-                         binop(Iop_CmpEQ32x4,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7F8000007F800000ull),
-                                        mkU64(0x7F8000007F800000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0ull), mkU64(0ull))));
-                     assign(t1,
-                         binop(Iop_CmpEQ32x4,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7F8000007F800000ull),
-                                        mkU64(0x7F8000007F800000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x7F8000007F800000ull),
-                                  mkU64(0x7F8000007F800000ull))));
-                     assign(t2,
-                            binop(Iop_SarN32x4,
-                                  getWReg(ws), mkU8(31)));
-                     assign(t3,
-                         binop(Iop_CmpEQ32x4,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x0040000000400000ull),
-                                        mkU64(0x0040000000400000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x0040000000400000ull),
-                                  mkU64(0x0040000000400000ull))));
-                     assign(t4,
-                         binop(Iop_CmpEQ32x4,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x007FFFFF007FFFFFULL),
-                                        mkU64(0x007FFFFF007FFFFFULL))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0ull), mkU64(0ull))));
-                     assign(t5,
-                         binop(Iop_Shl32x4,
-                            binop(Iop_OrV128,
-                               binop(Iop_AndV128,
-                                  mkexpr(t1),
-                                  binop(Iop_AndV128,
-                                        mkexpr(t4),
-                                        binop(Iop_64HLtoV128,
-                                           mkU64(0x100000001ull),
-                                           mkU64(0x100000001ull)))),
-                               binop(Iop_OrV128,
-                                  binop(Iop_AndV128,
-                                     mkexpr(t0),
-                                     binop(Iop_OrV128,
-                                        binop(Iop_AndV128,
-                                           mkexpr(t4),
-                                           binop(Iop_64HLtoV128,
-                                              mkU64(0x800000008ull),
-                                              mkU64(0x800000008ull))),
-                                        binop(Iop_AndV128,
-                                           unop(Iop_NotV128,
-                                              mkexpr(t4)),
-                                           binop(Iop_64HLtoV128,
-                                              mkU64(0x400000004ull),
-                                              mkU64(0x400000004ull))))),
-                                  binop(Iop_AndV128,
-                                     unop(Iop_NotV128,
-                                          mkexpr(t1)),
-                                     binop(Iop_AndV128,
-                                        unop(Iop_NotV128,
-                                           mkexpr(t0)),
-                                        binop(Iop_64HLtoV128,
-                                           mkU64(0x200000002ull),
-                                           mkU64(0x200000002ull)))))),
-                         binop(Iop_OrV128,
-                               binop(Iop_AndV128,
-                                     mkexpr(t2),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0x200000002ull),
-                                           mkU64(0x200000002ull))),
-                               binop(Iop_AndV128,
-                                     unop(Iop_NotV128,
-                                          mkexpr(t2)),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(0x600000006ull),
-                                           mkU64(0x600000006ull))))));
-                     putWReg(wd,
-                       binop(Iop_OrV128,
-                          mkexpr(t5),
-                          binop(Iop_AndV128,
-                             binop(Iop_CmpEQ32x4,
-                                mkexpr(t5),
-                                binop(Iop_64HLtoV128,
-                                      mkU64(0ull),
-                                      mkU64(0ull))),
-                             binop(Iop_OrV128,
-                                binop(Iop_AndV128,
-                                      mkexpr(t3),
-                                      binop(Iop_64HLtoV128,
-                                         mkU64(0x100000001ull),
-                                         mkU64(0x100000001ull))),
-                                binop(Iop_AndV128,
-                                      unop(Iop_NotV128, mkexpr(t3)),
-                                      binop(Iop_64HLtoV128,
-                                         mkU64(0x200000002ull),
-                                         mkU64(0x200000002ull)))))));
-                     break;
-                  }
+   switch (function) {
+         /* Cavium Specific instructions */
+      case 0x03:
+      case 0x32:
+      case 0x33:  /* DMUL, CINS , CINS32 */
+      case 0x3A:
+      case 0x3B:
+      case 0x2B:  /* EXT,  EXT32, SNE    */
 
-               case 0x01: { /* FCLASS.D */
-                     DIP("FCLASS.D w%d, w%d", wd, ws);
-                     assign(t0,
-                         binop(Iop_CmpEQ64x2,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FF0000000000000ull),
-                                        mkU64(0x7FF0000000000000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0ull), mkU64(0ull))));
-                     assign(t1,
-                         binop(Iop_CmpEQ64x2,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x7FF0000000000000ull),
-                                        mkU64(0x7FF0000000000000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x7FF0000000000000ull),
-                                  mkU64(0x7FF0000000000000ull))));
-                     assign(t2,
-                            binop(Iop_SarN64x2,
-                                  getWReg(ws), mkU8(63)));
-                     assign(t3,
-                         binop(Iop_CmpEQ64x2,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x0008000000000000ull),
-                                        mkU64(0x0008000000000000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x0008000000000000ull),
-                                  mkU64(0x0008000000000000ull))));
-                     assign(t4,
-                         binop(Iop_CmpEQ64x2,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x000FFFFFFFFFFFFFULL),
-                                        mkU64(0x000FFFFFFFFFFFFFULL))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0ull), mkU64(0ull))));
-                     assign(t5,
-                         binop(Iop_Shl64x2,
-                            binop(Iop_OrV128,
-                               binop(Iop_AndV128,
-                                  mkexpr(t1),
-                                  binop(Iop_AndV128,
-                                     mkexpr(t4),
-                                     binop(Iop_64HLtoV128,
-                                           mkU64(1ull),
-                                           mkU64(1ull)))),
-                               binop(Iop_OrV128,
-                                  binop(Iop_AndV128,
-                                     mkexpr(t0),
-                                     binop(Iop_OrV128,
-                                           binop(Iop_AndV128,
-                                                 mkexpr(t4),
-                                                 binop(Iop_64HLtoV128,
-                                                       mkU64(8ull),
-                                                       mkU64(8ull))),
-                                           binop(Iop_AndV128,
-                                                 unop(Iop_NotV128,
-                                                       mkexpr(t4)),
-                                                 binop(Iop_64HLtoV128,
-                                                       mkU64(4ull),
-                                                       mkU64(4ull))))),
-                                  binop(Iop_AndV128,
-                                     unop(Iop_NotV128,
-                                          mkexpr(t1)),
-                                     binop(Iop_AndV128,
-                                           unop(Iop_NotV128,
-                                                 mkexpr(t0)),
-                                           binop(Iop_64HLtoV128,
-                                                 mkU64(2ull),
-                                                 mkU64(2ull)))))),
-                            binop(Iop_OrV128,
-                               binop(Iop_AndV128,
-                                  mkexpr(t2),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(2ull),
-                                        mkU64(2ull))),
-                               binop(Iop_AndV128,
-                                  unop(Iop_NotV128,
-                                       mkexpr(t2)),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(6ull),
-                                        mkU64(6ull))))));
-                     putWReg(wd,
-                          binop(Iop_OrV128,
-                             mkexpr(t5),
-                             binop(Iop_AndV128,
-                                binop(Iop_CmpEQ64x2,
-                                      mkexpr(t5),
-                                      binop(Iop_64HLtoV128,
-                                            mkU64(0ull),
-                                            mkU64(0ull))),
-                                binop(Iop_OrV128,
-                                      binop(Iop_AndV128,
-                                            mkexpr(t3),
-                                            binop(Iop_64HLtoV128,
-                                                  mkU64(1ull),
-                                                  mkU64(1ull))),
-                                      binop(Iop_AndV128,
-                                            unop(Iop_NotV128,
-                                                 mkexpr(t3)),
-                                            binop(Iop_64HLtoV128,
-                                                  mkU64(2ull),
-                                                  mkU64(2ull)))))));
-                     break;
-                  }
+         /* CVM Compare Instructions */
+      case 0x2A:
+      case 0x2E:
+      case 0x2F:  /* SEQ,  SEQI,  SNEI   */
 
-               default:
-                  return -1;
-            }
+         /* CPU Load, Store, Memory, and Control Instructions */
+      case 0x18:
+      case 0x19:             /* SAA, SAAD */
+      case 0x1F:                        /* LAA, LAAD, LAI, LAID */
+      case 0x28:
+      case 0x2C:
+      case 0x2D:  /* BADDU, POP, DPOP */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            if (dis_instr_CVM(cins))
+               break;
 
-            break;
+            return -1;
+         } else {
+            return -1;
          }
 
-      case 0x191: { /* FTRUNC_S.df */
-            switch (df) {
-               case 0x00: { /* FTRUNC_S.W */
-                     DIP("FTRUNC_S.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTRUNCSW, 1);
-                     putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
-                     break;
-                  }
-
-               case 0x01: { /* FTRUNC_S.D */
-                     DIP("FTRUNC_S.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTRUNCSD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     assign(t3,
-                         binop(Iop_AndV128,
-                               unop(Iop_NotV128,
-                                    binop(Iop_CmpUN64Fx2,
-                                          getWReg(ws),
-                                          getWReg(ws))),
-                               binop(Iop_Max64Fx2,
-                                     getWReg(ws),
-                                     binop(Iop_64HLtoV128,
-                                        mkU64(0xC3E0000000000000),
-                                        mkU64(0xC3E0000000000000)))));
-                     assign(t1,
-                            binop(Iop_F64toI64S, mkU32(0x3),
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128to64, mkexpr(t3)))));
-                     assign(t2,
-                            binop(Iop_F64toI64S, mkU32(0x3),
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128HIto64, mkexpr(t3)))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
-
-               default:
-                  return -1;
-            }
+         break;
 
-            break;
-         }
+      case 0x02: {  /* MUL */
+         DIP("mul r%u, r%u, r%u", rd, rs, rt);
 
-      case 0x192: { /* FTRUNC_U.df */
-            switch (df) {
-               case 0x00: {  /* FTRUNC_U.W */
-                     DIP("FTRUNC_U.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTRUNCUW, 1);
-                     putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
-                     break;
-                  }
+         if (mode64) {
+            IRTemp tmpRs32 = newTemp(Ity_I32);
+            IRTemp tmpRt32 = newTemp(Ity_I32);
+            IRTemp tmpRes = newTemp(Ity_I32);
 
-               case 0x01: { /* FTRUNC_U.D */
-                     DIP("FTRUNC_U.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTRUNCUD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1,
-                            binop(Iop_F64toI64U,
-                                  mkU32(0x3),
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128to64,
-                                            getWReg(ws)))));
-                     assign(t2,
-                            binop(Iop_F64toI64U,
-                                  mkU32(0x3),
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128HIto64,
-                                            getWReg(ws)))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+            assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+            assign(tmpRes, binop(Iop_Mul32,
+                                 mkexpr(tmpRs32), mkexpr(tmpRt32)));
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
+         } else
+            putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
 
-               default:
-                  return -1;
-            }
+         break;
+      }
 
-            break;
-         }
+      case 0x00: {  /* MADD */
+         if (mode64) {
+            DIP("madd r%u, r%u", rs, rt);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I64);
+            t4 = newTemp(Ity_I64);
+            t5 = newTemp(Ity_I64);
+            t6 = newTemp(Ity_I32);
 
-      case 0x193: { /* FSQRT.df */
-            switch (df) {
-               case 0x00: { /* FSQRT.W */
-                     DIP("FSQRT.W w%d, w%d", wd, ws);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     calculateMSACSR(ws, wd, FSQRTW, 1);
-                     putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
-                     break;
-                  }
+            assign(t1, mkNarrowTo32(ty, getHI()));
+            assign(t2, mkNarrowTo32(ty, getLO()));
 
-               case 0x01: { /* FSQRT.D */
-                     DIP("FSQRT.D w%d, w%d", wd, ws);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     calculateMSACSR(ws, wd, FSQRTD, 1);
-                     putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
-                     break;
-                  }
+            assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+                             mkNarrowTo32(ty, getIReg(rt))));
 
-               default:
-                  return -1;
-            }
+            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+            assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
 
-            break;
-         }
+            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+         } else {
+            if ( (1 <= ac) && ( 3 >= ac) ) {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  /* If DSP is present -> DSP ASE MADD */
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-      case 0x194: { /* FRSQRT.df */
-            switch (df) {
-               case 0x00: { /* FRSQRT.W */
-                     DIP("FRSQRT.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FRSQRTW, 1);
-                     putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
-                     break;
+                  if (0 != retVal ) {
+                     return -2;
                   }
 
-               case 0x01: { /* FRSQRT.D */
-                     DIP("FRSQRT.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FRSQRTD, 1);
-                     putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
-                     break;
-                  }
+                  break;
+               } else {
+                  return -2;
+               }
+            } else {
+               DIP("madd r%u, r%u", rs, rt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I32);
+               t5 = newTemp(Ity_I32);
+               t6 = newTemp(Ity_I32);
 
-               default:
-                  return -1;
-            }
+               assign(t1, getHI());
+               assign(t2, getLO());
 
-            break;
-         }
+               assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
 
-      case 0x195: { /* FRCP.df */
-            switch (df) { /* FRCP.W */
-               case 0x00: {
-                     DIP("FRCP.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FRCPW, 1);
-                     putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
-                     break;
-                  }
+               assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+                                mkexpr(t3))));
 
-               case 0x01: { /* FRCP.D */
-                     DIP("FRCP.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FRCPD, 1);
-                     putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
-                     break;
-                  }
+               assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+                                                 unop(Iop_64to32, mkexpr(t3)))));
+               assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
 
-               default:
-                  return -1;
+               putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
+                                                       mkexpr(t3))));
+               putLO(mkexpr(t4));
+               break;
             }
-
-            break;
          }
 
-      case 0x196: { /* FRINT.df */
-            t1 = newTemp(Ity_V128);
-            t2 = newTemp(Ity_V128);
-            t3 = newTemp(Ity_V128);
-            t4 = newTemp(Ity_V128);
-            IRExpr *rm = get_IR_roundingmode_MSA();
-            assign(t1, getWReg(ws));
+         break;
+      }
 
-            switch (df) {
-               case 0x00: { /* FRINT.W */
-                     DIP("FRINT.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FRINTW, 1);
-                     assign(t2,
-                         binop(Iop_OrV128,
-                            binop(Iop_CmpLT32Fx4,
-                               mkexpr(t1),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0xCF000000CF000000ull),
-                                     mkU64(0xCF000000CF000000ull))),
-                            binop(Iop_CmpLT32Fx4,
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x4F0000004F000000ull),
-                                     mkU64(0x4F0000004F000000ull)),
-                               mkexpr(t1))));
-                     assign(t3,
-                         binop(Iop_CmpEQ32x4,
-                            binop(Iop_AndV128,
-                               mkexpr(t1),
-                               binop(Iop_64HLtoV128,
-                                     mkU64(0x0040000000400000ull),
-                                     mkU64(0x0040000000400000ull))),
-                            binop(Iop_64HLtoV128,
-                               mkU64(0x0040000000400000ull),
-                               mkU64(0x0040000000400000ull))));
-                     assign(t4,
-                            binop(Iop_CmpUN32Fx4,
-                                  mkexpr(t1), mkexpr(t1)));
-                     IRTemp tmp[4];
-                     Int i;
+      case 0x01: {  /* MADDU */
+         if (mode64) {
+            DIP("maddu r%u, r%u", rs, rt);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I64);
+            t4 = newTemp(Ity_I64);
+            t5 = newTemp(Ity_I64);
+            t6 = newTemp(Ity_I32);
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_I32);
-                        assign(tmp[i],
-                            unop(Iop_ReinterpF32asI32,
-                              binop(Iop_RoundF32toInt, rm,
-                                    unop(Iop_ReinterpI32asF32,
-                                         binop(Iop_GetElem32x4,
-                                               mkexpr(t1), mkU8(i))))));
-                     }
+            assign(t1, mkNarrowTo32(ty, getHI()));
+            assign(t2, mkNarrowTo32(ty, getLO()));
 
-                     putWReg(wd,
-                          binop(Iop_OrV128,
-                             binop(Iop_OrV128,
-                                binop(Iop_AndV128,
-                                      binop(Iop_OrV128,
-                                            mkexpr(t2),
-                                            binop(Iop_AndV128,
-                                                  mkexpr(t4),
-                                                  unop(Iop_NotV128,
-                                                        mkexpr(t3)))),
-                                      mkexpr(t1)),
-                                binop(Iop_AndV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t4),
-                                         mkexpr(t3)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x7FBFFFFF7FBFFFFF),
-                                         mkU64(0x7FBFFFFF7FBFFFFF)))),
-                             binop(Iop_AndV128,
-                                unop(Iop_NotV128,
-                                     binop(Iop_OrV128,
-                                           mkexpr(t2),
-                                           mkexpr(t4))),
-                                binop(Iop_OrV128,
-                                   binop(Iop_64HLtoV128,
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[3]),
-                                               mkexpr(tmp[2])),
-                                         binop(Iop_32HLto64,
-                                               mkexpr(tmp[1]),
-                                               mkexpr(tmp[0]))),
-                                   binop(Iop_AndV128,
-                                      mkexpr(t1),
-                                      binop(Iop_64HLtoV128,
-                                         mkU64(0x8000000080000000ull),
-                                         mkU64(0x8000000080000000ull)))
-                                ))));
-                     break;
-                  }
+            assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+                             mkNarrowTo32(ty, getIReg(rt))));
 
-               case 0x01: { /* FRINT.D */
-                     DIP("FRINT.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FRINTD, 1);
-                     assign(t2,
-                         binop(Iop_OrV128,
-                            binop(Iop_CmpLT64Fx2,
-                                  mkexpr(t1),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0xC3E0000000000000ull),
-                                        mkU64(0xC3E0000000000000ull))),
-                            binop(Iop_CmpLT64Fx2,
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x43E0000000000000ull),
-                                        mkU64(0x43E0000000000000ull)),
-                                  mkexpr(t1))));
-                     assign(t3,
-                         binop(Iop_CmpEQ64x2,
-                            binop(Iop_AndV128,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x0008000000000000ull),
-                                        mkU64(0x0008000000000000ull))),
-                            binop(Iop_64HLtoV128,
-                                  mkU64(0x0008000000000000ull),
-                                  mkU64(0x0008000000000000ull))));
-                     assign(t4,
-                            binop(Iop_CmpUN64Fx2,
-                                  mkexpr(t1), mkexpr(t1)));
-                     IRTemp tmp[2];
-                     Int i;
+            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+            assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_I64);
-                        assign(tmp[i],
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_RoundF64toInt, rm,
-                                       unop(Iop_ReinterpI64asF64,
-                                            binop(Iop_GetElem64x2,
-                                                  mkexpr(t1), mkU8(i))))));
-                     }
+            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+         } else {
+            if ( (1 <= ac) && ( 3 >= ac) ) {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  /* If DSP is present -> DSP ASE MADDU */
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                     putWReg(wd,
-                          binop(Iop_OrV128,
-                             binop(Iop_OrV128,
-                                binop(Iop_AndV128,
-                                      binop(Iop_OrV128,
-                                            mkexpr(t2),
-                                            binop(Iop_AndV128,
-                                                  mkexpr(t4),
-                                                  unop(Iop_NotV128,
-                                                        mkexpr(t3)))),
-                                      mkexpr(t1)),
-                                binop(Iop_AndV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t4),
-                                         mkexpr(t3)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x7FF7FFFFFFFFFFFF),
-                                         mkU64(0x7FF7FFFFFFFFFFFF)))),
-                             binop(Iop_AndV128,
-                                unop(Iop_NotV128,
-                                     binop(Iop_OrV128,
-                                           mkexpr(t2),
-                                           mkexpr(t4))),
-                                binop(Iop_OrV128,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(tmp[1]),
-                                         mkexpr(tmp[0])),
-                                   binop(Iop_AndV128,
-                                         mkexpr(t1),
-                                         binop(Iop_64HLtoV128,
-                                            mkU64(0x8000000000000000ull),
-                                            mkU64(0x8000000000000000ull))
-                                   )))));
-                     break;
+                  if (0 != retVal ) {
+                     return -2;
                   }
 
-               default:
-                  return -1;
-            }
-
-            break;
-         }
+                  break;
+               } else {
+                  return -2;
+               }
+            } else {
+               DIP("maddu r%u, r%u", rs, rt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I32);
+               t5 = newTemp(Ity_I32);
+               t6 = newTemp(Ity_I32);
 
-      case 0x197: { /* FLOG2.df */
+               assign(t1, getHI());
+               assign(t2, getLO());
 
-            switch (df) {
-               case 0x00: { /* FLOG2.W */
-                     DIP("FLOG2.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FLOG2W, 1);
-                     putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
-                     break;
-                  }
+               assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
 
-               case 0x01: { /* FLOG2.D */
-                     DIP("FLOG2.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FLOG2D, 1);
-                     putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
-                     break;
-                  }
+               assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+                                mkexpr(t3))));
+               assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+                                                 unop(Iop_64to32, mkexpr(t3)))));
+               assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
 
-               default:
-                  return -1;
+               putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
+                                                       mkexpr(t3))));
+               putLO(mkexpr(t4));
+               break;
             }
-
-            break;
          }
 
-      case 0x198: { /* FEXUPL.df */
-            switch (df) {
-               case 0x00: { /* FEXUPL.W */
-                     DIP("FEXUPL.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FEXUPLW, 1);
-                     putWReg(wd,
-                             unop(Iop_F16toF32x4,
-                                  unop(Iop_V128HIto64,
-                                       getWReg(ws))));
-                     break;
-                  }
-
-               case 0x01: { /* FEXUPL.D */
-                     DIP("FEXUPL.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FEXUPLD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1,
-                            unop(Iop_ReinterpF64asI64,
-                                 unop(Iop_F32toF64,
-                                      unop(Iop_ReinterpI32asF32,
-                                           unop(Iop_64to32,
-                                                unop(Iop_V128HIto64,
-                                                     getWReg(ws)))))));
-                     assign(t2,
-                            unop(Iop_ReinterpF64asI64,
-                                 unop(Iop_F32toF64,
-                                      unop(Iop_ReinterpI32asF32,
-                                           unop(Iop_64HIto32,
-                                                unop(Iop_V128HIto64,
-                                                     getWReg(ws)))))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
-
-               default:
-                  return -1;
-            }
-
-            break;
-         }
+         break;
+      }
 
-      case 0x199: { /* FEXUPR.df */
-            switch (df) {
-               case 0x00: { /* FEXUPR.W */
-                     DIP("FEXUPR.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FEXUPRW, 1);
-                     putWReg(wd,
-                             unop(Iop_F16toF32x4,
-                                  unop(Iop_V128to64,
-                                       getWReg(ws))));
-                     break;
-                  }
+      case 0x04: {  /* MSUB */
+         if (mode64) {
+            DIP("msub r%u, r%u", rs, rt);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I64);
+            t4 = newTemp(Ity_I64);
+            t5 = newTemp(Ity_I64);
+            t6 = newTemp(Ity_I32);
 
-               case 0x01: { /* FEXUPR.D */
-                     DIP("FEXUPR.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FEXUPRD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1,
-                            unop(Iop_ReinterpF64asI64,
-                                 unop(Iop_F32toF64,
-                                      unop(Iop_ReinterpI32asF32,
-                                           unop(Iop_64to32,
-                                                unop(Iop_V128to64,
-                                                     getWReg(ws)))))));
-                     assign(t2,
-                            unop(Iop_ReinterpF64asI64,
-                                 unop(Iop_F32toF64,
-                                      unop(Iop_ReinterpI32asF32,
-                                           unop(Iop_64HIto32,
-                                                unop(Iop_V128to64,
-                                                     getWReg(ws)))))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+            assign(t1, mkNarrowTo32(ty, getHI()));
+            assign(t2, mkNarrowTo32(ty, getLO()));
 
-               default:
-                  return -1;
-            }
+            assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+                             mkNarrowTo32(ty, getIReg(rt))));
 
-            break;
-         }
+            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+            assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
 
-      case 0x19A: { /* FFQL.df */
-            switch (df) {
-               case 0x00: { /* FFQL.W */
-                     DIP("FFQL.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFQLW, 1);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveHI16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2,
-                            binop(Iop_32HLto64,
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(1)))),
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(0))))));
-                     assign(t3,
-                            binop(Iop_32HLto64,
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(3)))),
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(2))))));
-                     putWReg(wd,
-                             triop(Iop_Div32Fx4, rm,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x4700000047000000),
-                                         mkU64(0x4700000047000000))));
-                     break;
-                  }
+            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+         } else {
+            if ( (1 <= ac) && ( 3 >= ac) ) {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  /* If DSP is present -> DSP ASE MSUB */
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-               case 0x01: { /* FFQL.D */
-                     DIP("FFQL.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFQLD, 1);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveHI32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64StoF64, rm,
-                                       unop(Iop_V128to64,
-                                            mkexpr(t1)))));
-                     assign(t3,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64StoF64, rm,
-                                       unop(Iop_V128HIto64,
-                                            mkexpr(t1)))));
-                     putWReg(wd,
-                             triop(Iop_Div64Fx2, rm,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x41E0000000000000),
-                                         mkU64(0x41E0000000000000))));
-                     break;
+                  if (0 != retVal ) {
+                     return -2;
                   }
 
-               default:
-                  return -1;
-            }
+                  break;
+               } else {
+                  return -2;
+               }
+            } else {
+               DIP("msub r%u, r%u", rs, rt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I32);
+               t5 = newTemp(Ity_I1);
+               t6 = newTemp(Ity_I32);
 
-            break;
-         }
+               assign(t1, getHI());
+               assign(t2, getLO());
 
-      case 0x19B: { /* FFQR.df */
-            switch (df) {
-               case 0x00: { /* FFQR.W */
-                     DIP("FFQR.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFQRW, 1);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_SarN32x4,
-                                  binop(Iop_InterleaveLO16x8,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(16)));
-                     assign(t2,
-                            binop(Iop_32HLto64,
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(1)))),
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(0))))));
-                     assign(t3,
-                            binop(Iop_32HLto64,
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(3)))),
-                                  unop(Iop_ReinterpF32asI32,
-                                       binop(Iop_I32StoF32, rm,
-                                             binop(Iop_GetElem32x4,
-                                                   mkexpr(t1),
-                                                   mkU8(2))))));
-                     putWReg(wd,
-                             triop(Iop_Div32Fx4, rm,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x4700000047000000),
-                                         mkU64(0x4700000047000000))));
-                     break;
-                  }
+               assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+               assign(t4, unop(Iop_64to32, mkexpr(t3)));  /* new lo */
 
-               case 0x01: { /* FFQR.D */
-                     DIP("FFQR.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFQRD, 1);
-                     t1 = newTemp(Ity_V128);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I64);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_SarN64x2,
-                                  binop(Iop_InterleaveLO32x4,
-                                        getWReg(ws),
-                                        getWReg(ws)),
-                                  mkU8(32)));
-                     assign(t2,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64StoF64, rm,
-                                       unop(Iop_V128to64,
-                                            mkexpr(t1)))));
-                     assign(t3,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64StoF64, rm,
-                                       unop(Iop_V128HIto64,
-                                            mkexpr(t1)))));
-                     putWReg(wd,
-                             triop(Iop_Div64Fx2, rm,
-                                   binop(Iop_64HLtoV128,
-                                         mkexpr(t3), mkexpr(t2)),
-                                   binop(Iop_64HLtoV128,
-                                         mkU64(0x41E0000000000000),
-                                         mkU64(0x41E0000000000000))));
-                     break;
-                  }
+               /* if lo<lo(mul) hi = hi - 1 */
+               assign(t5, binop(Iop_CmpLT32U,
+                                mkexpr(t2),
+                                mkexpr(t4)));
 
-               default:
-                  return -1;
-            }
+               assign(t6, IRExpr_ITE(mkexpr(t5),
+                                     binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
+                                     mkexpr(t1)));
 
-            break;
+               putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
+                                                       mkexpr(t3))));
+               putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+               break;
+            }
          }
 
-      case 0x19C: { /* FTINT_S.df */
-            switch (df) { /* FTINT_S.W */
-               case 0x00: {
-                     DIP("FTINT_S.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTINT_SW, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_I32);
-                     assign(t3,
-                         binop(Iop_AndV128,
-                               unop(Iop_NotV128,
-                                    binop(Iop_CmpUN32Fx4,
-                                          getWReg(ws),
-                                          getWReg(ws))),
-                               binop(Iop_Max32Fx4,
-                                     getWReg(ws),
-                                     binop(Iop_64HLtoV128,
-                                        mkU64(0xCF000000CF000000),
-                                        mkU64(0xCF000000CF000000)))));
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                         binop(Iop_32HLto64,
-                               binop(Iop_F32toI32S, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t3), mkU8(1)))),
-                               binop(Iop_F32toI32S, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t3), mkU8(0))))));
-                     assign(t2,
-                         binop(Iop_32HLto64,
-                               binop(Iop_F32toI32S, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t3), mkU8(3)))),
-                               binop(Iop_F32toI32S, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                mkexpr(t3), mkU8(2))))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+         break;
+      }
 
-               case 0x01: {  /* FTINT_S.D */
-                     DIP("FTINT_S.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTINT_SD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     assign(t3,
-                         binop(Iop_AndV128,
-                               unop(Iop_NotV128,
-                                    binop(Iop_CmpUN64Fx2,
-                                          getWReg(ws),
-                                          getWReg(ws))),
-                               binop(Iop_Max64Fx2,
-                                     getWReg(ws),
-                                     binop(Iop_64HLtoV128,
-                                        mkU64(0xC3E0000000000000),
-                                        mkU64(0xC3E0000000000000)))));
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_F64toI64S, rm,
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128to64, mkexpr(t3)))));
-                     assign(t2,
-                            binop(Iop_F64toI64S, rm,
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128HIto64, mkexpr(t3)))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+      case 0x05: {  /* MSUBU */
+         if (mode64) {
+            DIP("msubu r%u, r%u", rs, rt);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I64);
+            t4 = newTemp(Ity_I64);
+            t5 = newTemp(Ity_I64);
+            t6 = newTemp(Ity_I32);
 
-               default:
-                  return -1;
-            }
+            assign(t1, mkNarrowTo32(ty, getHI()));
+            assign(t2, mkNarrowTo32(ty, getLO()));
 
-            break;
-         }
+            assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+                             mkNarrowTo32(ty, getIReg(rt))));
 
-      case 0x19D: {/* FTINT_U.df */
-            switch (df) { /* FTINT_U.W */
-               case 0x00: {
-                     DIP("FTINT_U.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTINT_UW, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_V128);
-                     t4 = newTemp(Ity_V128);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                         binop(Iop_32HLto64,
-                               binop(Iop_F32toI32U, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                getWReg(ws), mkU8(1)))),
-                               binop(Iop_F32toI32U, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                getWReg(ws), mkU8(0))))));
-                     assign(t2,
-                         binop(Iop_32HLto64,
-                               binop(Iop_F32toI32U, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                getWReg(ws), mkU8(3)))),
-                               binop(Iop_F32toI32U, rm,
-                                     unop(Iop_ReinterpI32asF32,
-                                          binop(Iop_GetElem32x4,
-                                                getWReg(ws), mkU8(2))))));
-                     assign(t3,
-                            unop(Iop_NotV128,
-                                 binop(Iop_SarN32x4,
-                                       getWReg(ws),
-                                       mkU8(31))));
-                     assign(t4,
-                            binop(Iop_CmpLT32Fx4,
-                                  getWReg(ws),
-                                  binop(Iop_64HLtoV128,
-                                        mkU64(0x4EFFFFFF4EFFFFFF),
-                                        mkU64(0x4EFFFFFF4EFFFFFF))));
-                     putWReg(wd,
-                             binop(Iop_OrV128,
-                                   binop(Iop_AndV128,
-                                         mkexpr(t4),
-                                         binop(Iop_AndV128,
-                                               binop(Iop_64HLtoV128,
-                                                     mkexpr(t2),
-                                                     mkexpr(t1)),
-                                               mkexpr(t3))),
-                                   binop(Iop_AndV128,
-                                         unop(Iop_NotV128, mkexpr(t4)),
-                                         unop(Iop_F32toI32Ux4_RZ,
-                                              getWReg(ws)))));
-                     break;
-                  }
+            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+            assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
 
-               case 0x01: {  /* FTINT_U.D */
-                     DIP("FTINT_U.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wd, FTINT_UD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     IRExpr *rm = get_IR_roundingmode_MSA();
-                     assign(t1,
-                            binop(Iop_F64toI64U, rm,
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128to64,
-                                            getWReg(ws)))));
-                     assign(t2,
-                            binop(Iop_F64toI64U, rm,
-                                  unop(Iop_ReinterpI64asF64,
-                                       unop(Iop_V128HIto64,
-                                            getWReg(ws)))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+         } else {
+            if ( (1 <= ac) && ( 3 >= ac) ) {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  /* If DSP is present -> DSP ASE MSUBU */
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-               default:
-                  return -1;
-            }
+                  if (0 != retVal ) {
+                     return -2;
+                  }
 
-            break;
-         }
+                  break;
+               } else {
+                  return -2;
+               }
+            } else {
+               DIP("msubu r%u, r%u", rs, rt);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I64);
+               t4 = newTemp(Ity_I32);
+               t5 = newTemp(Ity_I1);
+               t6 = newTemp(Ity_I32);
 
-      case 0x19E: { /* FFINT_S.df */
-            t1 = newTemp(Ity_V128);
-            assign(t1, getWReg(ws));
-            IRExpr *rm = get_IR_roundingmode_MSA();
+               assign(t1, getHI());
+               assign(t2, getLO());
 
-            switch (df) {
-               case 0x00: { /* FFINT_S.W */
-                     DIP("FFINT_S.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFINTSW, 1);
-                     IRTemp tmp[4];
-                     Int i;
+               assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+               assign(t4, unop(Iop_64to32, mkexpr(t3)));  /* new lo */
 
-                     for (i = 0; i < 4; i++) {
-                        tmp[i] = newTemp(Ity_F32);
-                        assign(tmp[i],
-                               binop(Iop_I32StoF32, rm,
-                                     binop(Iop_GetElem32x4,
-                                           mkexpr(t1), mkU8(i))));
-                     }
+               /* if lo<lo(mul) hi = hi - 1 */
+               assign(t5, binop(Iop_CmpLT32U,
+                                mkexpr(t2),
+                                mkexpr(t4)));
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[3])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[2]))),
-                                   binop(Iop_32HLto64,
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[1])),
-                                         unop(Iop_ReinterpF32asI32,
-                                              mkexpr(tmp[0])))));
-                     break;
-                  }
+               assign(t6, IRExpr_ITE(mkexpr(t5),
+                                     binop(Iop_Sub32,
+                                           mkexpr(t1),
+                                           mkU32(0x1)),
+                                     mkexpr(t1)));
 
-               case 0x01: { /* FFINT_S.D */
-                     DIP("FFINT_S.D w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFINTSD, 1);
-                     IRTemp tmp[2];
-                     Int i;
+               putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
+                                                       mkexpr(t3))));
+               putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+               break;
+            }
+         }
 
-                     for (i = 0; i < 2; i++) {
-                        tmp[i] = newTemp(Ity_F64);
-                        assign(tmp[i],
-                               binop(Iop_I64StoF64, rm,
-                                     binop(Iop_GetElem64x2,
-                                           mkexpr(t1), mkU8(i))));
-                     }
+         break;
+      }
 
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[1])),
-                                   unop(Iop_ReinterpF64asI64,
-                                        mkexpr(tmp[0]))));
-                     break;
-                  }
+      case 0x6:  /* dmul MIPS64 - Netlogic */
+         DIP("dmul r%u, r%u, r%u", rd, rs, rt);
+         t0 = newTemp(Ity_I128);
 
-               default:
-                  return -1;
-            }
+         assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
 
-            break;
-         }
+         putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
+         break;
 
-      case 0x19F: { /* FFINT_U.df */
-            IRExpr *rm = get_IR_roundingmode_MSA();
+      case 0x10:  /* LDADDW - Swap Word - Netlogic */
+         DIP("ldaddw r%u, r%u", rt, rs);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
 
-            switch (df) {
-               case 0x00: { /* FFINT_U.W */
-                     DIP("FFINT_U.W w%d, w%d", wd, ws);
-                     calculateMSACSR(ws, wt, FFINT_UW, 1);
-                     putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
-                     break;
-                  }
+         /* v = GPR[rt] */
+         assign(t0, mkNarrowTo32(ty, getIReg(rt)));
 
-               case 0x01: { /* FFINT_U.D */
-                     DIP("FFINT_U.D w%d, w%d",
-                         wd, ws);
-                     calculateMSACSR(ws, wt,
-                                     FFINT_UD, 1);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     assign(t1,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64UtoF64, rm,
-                                       unop(Iop_V128to64,
-                                            getWReg(ws)))));
-                     assign(t2,
-                            unop(Iop_ReinterpF64asI64,
-                                 binop(Iop_I64UtoF64, rm,
-                                       unop(Iop_V128HIto64,
-                                            getWReg(ws)))));
-                     putWReg(wd,
-                             binop(Iop_64HLtoV128,
-                                   mkexpr(t2), mkexpr(t1)));
-                     break;
-                  }
+         /* GPR[rt] = memory[base]; */
+         assign(t1, load(Ity_I32, getIReg(rs)));
+         putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
 
-               default:
-                  return -1;
-            }
+         /* memory[base] = memory[base] + v; */
+         store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
+         break;
 
-            break;
-         }
+      case 0x12:  /* LDADDD - Swap Word - Netlogic */
+         DIP("ldaddw r%u, r%u", rt, rs);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
 
-      default:
-         return -1;
-   }
+         /*  v = GPR[rt] */
+         assign(t0, getIReg(rt));
 
-   return 0;
-}
+         /* GPR[rt] = memory[base]; */
+         assign(t1, load(Ity_I64, getIReg(rs)));
+         putIReg(rt, mkexpr(t1));
 
-static Int msa_MI10_load(UInt cins, UChar wd, UChar ws) { /* MI10 (0x20) */
-   IRTemp t1;
-   UShort i10;
-   UChar df;
+         /* memory[base] = memory[base] + v; */
+         store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
+         break;
 
-   i10 = (cins & 0x03FF0000) >> 16;
-   df = cins & 0x00000003;
+      case 0x14:  /* SWAPW - Swap Word - Netlogic */
+         DIP("swapw r%u, r%u", rt, rs);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+         assign(t1, load(Ity_I32, getIReg(rs)));
+         putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+         store(getIReg(rs), mkexpr(t0));
+         break;
 
-   switch (df) {
-      case 0x00: { /* LD.B */
-            DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10);
-            putWReg(wd, load(Ity_V128, mkexpr(t1)));
-            break;
-         }
+      case 0x16:  /* SWAPD - Swap Double - Netlogic */
+         DIP("swapw r%u, r%u", rt, rs);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         assign(t0, getIReg(rt));
+         assign(t1, load(Ity_I64, getIReg(rs)));
+         putIReg(rt, mkexpr(t1));
+         store(getIReg(rs), mkexpr(t0));
+         break;
 
-      case 0x01: { /* LD.H */
-            DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 1);
-#if defined (_MIPSEL)
-            putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
-            putWReg(wd,
-                    unop(Iop_Reverse8sIn16_x8,
-                         load(Ity_V128, mkexpr(t1))));
-#endif
-            break;
-         }
+      case 0x20: {  /* CLZ */
+         DIP("clz r%u, r%u", rd, rs);
 
-      case 0x02: { /* LD.W */
-            DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 2);
-#if defined (_MIPSEL)
-            putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
-            putWReg(wd,
-                    unop(Iop_Reverse8sIn32_x4,
-                         load(Ity_V128, mkexpr(t1))));
-#endif
-            break;
-         }
+         if (mode64) {
+            IRTemp tmpClz32 = newTemp(Ity_I32);
+            IRTemp tmpRs32 = newTemp(Ity_I32);
 
-      case 0x03: { /* LD.D */
-            DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 3);
-#if defined (_MIPSEL)
-            putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
-            putWReg(wd,
-                    unop(Iop_Reverse8sIn64_x2,
-                         load(Ity_V128, mkexpr(t1))));
-#endif
-            break;
+            assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+            assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+         } else {
+            t1 = newTemp(Ity_I1);
+            assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
+            putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                   mkU32(0x00000020),
+                                   unop(Iop_Clz32, getIReg(rs))));
          }
 
-      default:
-         return -1;
-   }
+         break;
+      }
 
-   return 0;
-}
+      case 0x21: {  /* CLO */
+         DIP("clo r%u, r%u", rd, rs);
 
-static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) { /* MI10 (0x24) */
-   IRTemp t1;
-   UShort i10;
-   UChar df;
+         if (mode64) {
+            IRTemp tmpClo32 = newTemp(Ity_I32);
+            IRTemp tmpRs32 = newTemp(Ity_I32);
+            assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
 
-   df = cins & 0x00000003;
-   i10 = (cins & 0x03FF0000) >> 16;
+            t1 = newTemp(Ity_I1);
+            assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
+            assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
+                                        mkU32(0x00000020),
+                                        unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
 
-   switch (df) {
-      case 0x00: { /* ST.B */
-            DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10);
-            store(mkexpr(t1), getWReg(wd));
+            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
             break;
-         }
-
-      case 0x01: { /* ST.H */
-            DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 1);
-#if defined (_MIPSEL)
-            store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
-            store(mkexpr(t1),
-                  unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
-#endif
+         } else {
+            t1 = newTemp(Ity_I1);
+            assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
+            putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                   mkU32(0x00000020),
+                                   unop(Iop_Clz32,
+                                        unop(Iop_Not32, getIReg(rs)))));
             break;
          }
+      }
 
-      case 0x02: { /* ST.W */
-            DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 2);
-#if defined (_MIPSEL)
-            store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
-            store(mkexpr(t1),
-                  unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
-#endif
-            break;
-         }
+      case 0x24:  /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
+         DIP("dclz r%u, r%u", rd, rs);
+         t1 = newTemp(Ity_I1);
+         assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                mkU64(0x00000040),
+                                unop(Iop_Clz64, getIReg(rs))));
+         break;
 
-      case 0x03: { /* ST.D */
-            DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
-            LOAD_STORE_PATTERN_MSA(i10 << 3);
-#if defined (_MIPSEL)
-            store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
-            store(mkexpr(t1),
-                  unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
-#endif
-            break;
-         }
+      case 0x25:  /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
+         DIP("dclo r%u, r%u", rd, rs);
+         t1 = newTemp(Ity_I1);
+         assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
+                          mkU64(0xffffffffffffffffULL)));
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                mkU64(0x40),
+                                unop(Iop_Clz64, unop(Iop_Not64,
+                                      getIReg(rs)))));
+         break;
 
       default:
          return -1;
@@ -25783,7536 +18852,6177 @@ static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) { /* MI10 (0x24) */
    return 0;
 }
 
-/*------------------------------------------------------------*/
-/*---   Disassemble a single MIPS MSA (SIMD) instruction   ---*/
-/*---   Return values:                                     ---*/
-/*---       0: Success                                     ---*/
-/*---      -1: Decode failure (unknown instruction)        ---*/
-/*---      -2: Illegal instruction                         ---*/
-/*------------------------------------------------------------*/
-static Int disMSAInstr_MIPS_WRK ( UInt cins ) {
-   UChar minor_opcode, wd, ws;
-
-   vassert(has_msa);
-   vassert((cins & 0xFC000000) == 0x78000000);
-
-   minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
-   wd = (cins & 0x000007C0) >> 6;
-   ws = (cins & 0x0000F800) >> 11;
-
-   switch (minor_opcode) {
-      case 0x0:
-         return msa_I8_logical(cins, wd, ws);
-
-      case 0x01:
-         return msa_I8_branch(cins, wd, ws);
-
-      case 0x02:
-         return msa_I8_shift(cins, wd, ws);
-
-      case 0x06:
-         return msa_I5_06(cins, wd, ws);
-
-      case 0x07:
-         return msa_I5_07(cins, wd, ws);
-
-      case 0x09:
-         return msa_BIT_09(cins, wd, ws);
-
-      case 0x0A:
-         return msa_BIT_0A(cins, wd, ws);
+static UInt disInstr_MIPS_WRK_Special3(UInt cins, const VexArchInfo* archinfo,
+                                       const VexAbiInfo*  abiinfo, DisResult* dres,
+                                       IRStmt** bstmt, IRExpr** lastn,
+                                       Bool(*resteerOkFn) (/*opaque */void *,
+                                             Addr),
+                                       void*        callback_opaque)
 
-      case 0x0D:
-         return msa_3R_0D(cins, wd, ws);
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
+   UInt rs, rt, rd, sa, function, imm, instr_index, msb, lsb, size;
+   /* Additional variables for instruction fields in DSP ASE insructions */
 
-      case 0x0E:
-         return msa_3R_0E(cins, wd, ws);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+   instr_index = get_instr_index(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
 
-      case 0x0F:
-         return msa_3R_0F(cins, wd, ws);
+   switch (function) {
+      case 0x01: {  /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         UInt srcPos = lsb;
+         UInt dstSz = msb + 33;
+         t1 = newTemp(Ity_I64);
+         DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
 
-      case 0x10:
-         return msa_3R_10(cins, wd, ws);
+         UChar lsAmt = 64 - (srcPos + dstSz);  /* left shift amount; */
+         UChar rsAmt = 64 - dstSz;  /* right shift amount; */
 
-      case 0x11:
-         return msa_3R_11(cins, wd, ws);
+         assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+         putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
 
-      case 0x12:
-         return msa_3R_12(cins, wd, ws);
+         break;
+      }
 
-      case 0x13:
-         return msa_3R_13(cins, wd, ws);
+      case 0x02: {  /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         UInt srcPos = lsb + 32;
+         UInt dstSz = msb + 1;
+         DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
+         t1 = newTemp(Ity_I64);
 
-      case 0x14:
-         return msa_3R_14(cins, wd, ws);
+         vassert(srcPos >= 32 && srcPos < 64);
+         vassert(dstSz > 0 && dstSz <= 32);
+         vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
 
-      case 0x15:
-         return msa_3R_15(cins, wd, ws);
+         UChar lsAmt = 64 - (srcPos + dstSz);  /* left shift amount; */
+         UChar rsAmt = 64 - dstSz;  /* right shift amount; */
 
-      case 0x19:
-         return msa_ELM(cins, wd, ws);
+         assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+         putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+         break;
+      }
 
-      case 0x1A:
-         return msa_3R_1A(cins, wd, ws);
+      case 0x05: {  /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         UInt dstPos = lsb;
+         UInt srcSz = msb - lsb + 33;
+         t1 = newTemp(ty);
+         t2 = newTemp(ty);
+         t3 = newTemp(ty);
+         t4 = newTemp(ty);
+         IRTemp tmpT1 = newTemp(ty);
+         IRTemp tmpT2 = newTemp(ty);
+         IRTemp tmpT3 = newTemp(ty);
+         IRTemp tmpT4 = newTemp(ty);
+         IRTemp tmpT5 = newTemp(ty);
+         IRTemp tmpT6 = newTemp(ty);
+         IRTemp tmpT7 = newTemp(ty);
+         IRTemp tmpRs = newTemp(ty);
+         IRTemp tmpRt = newTemp(ty);
+         IRTemp tmpRd = newTemp(ty);
 
-      case 0x1B:
-         return msa_3R_1B(cins, wd, ws);
+         assign(tmpRs, getIReg(rs));
+         assign(tmpRt, getIReg(rt));
+         DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
 
-      case 0x1C:
-         return msa_3R_1C(cins, wd, ws);
+         UChar lsAmt = dstPos + srcSz - 1;   /* left shift amount; */
+         UChar rsAmt = dstPos + srcSz - 1;   /* right shift amount; */
 
-      case 0x1E:
-         if ((cins & 0x03000000) == 0)
-            return msa_VEC(cins, wd, ws);
-         else if ((cins & 0x00200000) == 0)
-            return msa_2R(cins, wd, ws);
-         else
-            return msa_2RF(cins, wd, ws);
+         assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+         assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
+         assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
+         assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
 
-      case 0x20:
-         return msa_MI10_load(cins, wd, ws);
+         lsAmt = 63 - dstPos; /* left shift amount; */
+         rsAmt = 63 - dstPos; /* right shift amount; */
 
-      case 0x24:
-         return msa_MI10_store(cins, wd, ws);
-   }
+         assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+         assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
+         assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
+         assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
 
-   return -1;
-}
+         /* extract size from src register */
+         lsAmt = 64 - srcSz;  /* left shift amount; */
+         rsAmt = 64 - (lsb + srcSz);   /* right shift amount; */
 
-/*------------------------------------------------------------*/
-/*---          Disassemble a single instruction            ---*/
-/*------------------------------------------------------------*/
+         assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+         assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
 
-/* Disassemble a single instruction into IR. The instruction is
-   located in host memory at guest_instr, and has guest IP of
-   guest_PC_curr_instr, which will have been set before the call
-   here. */
+         assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
+         assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
+         putIReg(rt, mkexpr(tmpRd));
+         break;
+      }
 
-static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
-                                                                    Addr),
-                                     Bool         resteerCisOk,
-                                     void*        callback_opaque,
-                                     Long         delta64,
-                                     const VexArchInfo* archinfo,
-                                     const VexAbiInfo*  abiinfo,
-                                     Bool         sigill_diag )
-{
-   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
+      case 0x06: {  /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         UInt dstPos = lsb + 32;
+         UInt srcSz = msb - lsb + 1;
+         IRTemp tmpT1 = newTemp(ty);
+         IRTemp tmpT2 = newTemp(ty);
+         IRTemp tmpT3 = newTemp(ty);
+         IRTemp tmpT4 = newTemp(ty);
+         IRTemp tmpT5 = newTemp(ty);
+         IRTemp tmpT6 = newTemp(ty);
+         IRTemp tmpT7 = newTemp(ty);
+         IRTemp tmpT8 = newTemp(ty);
+         IRTemp tmpT9 = newTemp(ty);
+         IRTemp tmpRs = newTemp(ty);
+         IRTemp tmpRt = newTemp(ty);
+         IRTemp tmpRd = newTemp(ty);
 
-   UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
-        trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
-   /* Additional variables for instruction fields in DSP ASE insructions */
-   UInt ac;
+         assign(tmpRs, getIReg(rs));
+         assign(tmpRt, getIReg(rt));
+         DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
 
-   DisResult dres;
+         UChar lsAmt = 64 - srcSz;  /* left shift amount; */
+         UChar rsAmt = 64 - (dstPos + srcSz);  /* right shift amount; */
+         assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+         assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
 
-   static IRExpr *lastn = NULL;  /* last jump addr */
-   static IRStmt *bstmt = NULL;  /* branch (Exit) stmt */
+         lsAmt = 64 - dstPos;  /* left shift amount; */
+         rsAmt = 64 - dstPos;  /* right shift amount; */
+         assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+         assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
 
-   /* The running delta */
-   Int delta = (Int) delta64;
+         lsAmt = dstPos;  /* left shift amount; */
+         rsAmt = srcSz;  /* right shift amount; */
+         assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+         assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
 
-   /* Holds eip at the start of the insn, so that we can print
-      consistent error messages for unimplemented insns. */
-   Int delta_start = delta;
+         assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
+         assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
 
-   /* Are we in a delay slot ? */
-   Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
+         assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
+         assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
+         putIReg(rt, mkexpr(tmpRd));
+         break;
+      }
 
-   /* Set result defaults. */
-   dres.whatNext = Dis_Continue;
-   dres.len = 0;
-   dres.continueAt = 0;
-   dres.jk_StopHere = Ijk_INVALID;
-   dres.hint        = Dis_HintNone;
+      case 0x07: {  /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
+         IRTemp tmp1 = newTemp(ty);
+         IRTemp tmpT1 = newTemp(ty);
+         IRTemp tmpT2 = newTemp(ty);
+         IRTemp tmpT3 = newTemp(ty);
+         IRTemp tmpT4 = newTemp(ty);
+         IRTemp tmpT5 = newTemp(ty);
+         IRTemp tmpT6 = newTemp(ty);
+         IRTemp tmpT7 = newTemp(ty);
+         IRTemp tmpT8 = newTemp(ty);
+         IRTemp tmpT9 = newTemp(ty);
+         IRTemp tmp = newTemp(ty);
+         IRTemp tmpRs = newTemp(ty);
+         IRTemp tmpRt = newTemp(ty);
+         IRTemp tmpRd = newTemp(ty);
 
-   delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
+         assign(tmpRs, getIReg(rs));
+         assign(tmpRt, getIReg(rt));
 
-   const UChar *code = guest_code + delta;
-   cins = getUInt(code);
-   DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
+             msb - lsb + 1);
+         UChar lsAmt = 63 - lsb;  /* left shift amount; */
+         UChar rsAmt = 63 - lsb;  /* right shift amount; */
+         assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+         assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+         assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
+         assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
+
+         lsAmt = msb;  /* left shift amount; */
+         rsAmt = 1;  /*right shift amount; */
+         assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+         assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
+         assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
+         assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
+
+         lsAmt = 64 - (msb - lsb + 1);  /* left shift amount; */
+         rsAmt = 64 - (msb + 1);  /* right shift amount; */
+         assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+         assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
+
+         assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
+         assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
+         putIReg(rt, mkexpr(tmpRd));
+         break;
+      }
 
-   if (delta != 0) {
-      if (branch_or_jump(guest_code + delta - 4)) {
-         if (lastn == NULL && bstmt == NULL) {
-            vassert(0);
-         } else {
-            dres.whatNext = Dis_StopHere;
-            if (lastn != NULL) {
-               delay_slot_jump = True;
-            } else if (bstmt != NULL) {
-               delay_slot_branch = True;
+      case 0x24:  /* DBSHFL */
+         lsb = get_lsb(cins);
+         IRTemp tmpRs = newTemp(ty);
+         IRTemp tmpRt = newTemp(ty);
+         IRTemp tmpRd = newTemp(ty);
+         assign(tmpRs, getIReg(rs));
+         assign(tmpRt, getIReg(rt));
+
+         switch (lsb) {
+            case 0x02: {  /* DSBH */
+               DIP("dsbh r%u, r%u", rd, rt);
+               IRTemp tmpT1 = newTemp(ty);
+               IRTemp tmpT2 = newTemp(ty);
+               IRTemp tmpT3 = newTemp(ty);
+               IRTemp tmpT4 = newTemp(ty);
+               IRTemp tmpT5 = newTemp(Ity_I64);
+               IRTemp tmpT6 = newTemp(ty);
+               assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
+               assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
+               assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
+               assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
+               assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
+               assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
+               assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
+               putIReg(rd, mkexpr(tmpRd));
+               break;
             }
-         }
-      }
 
-      if (branch_or_link_likely(guest_code + delta - 4)) {
-         likely_delay_slot = True;
-      }
-   }
+            case 0x05: {  /* DSHD */
+               DIP("dshd r%u, r%u\n", rd, rt);
+               IRTemp tmpT1 = newTemp(ty);
+               IRTemp tmpT2 = newTemp(ty);
+               IRTemp tmpT3 = newTemp(ty);
+               IRTemp tmpT4 = newTemp(ty);
+               IRTemp tmpT5 = newTemp(Ity_I64);
+               IRTemp tmpT6 = newTemp(ty);
+               IRTemp tmpT7 = newTemp(ty);
+               IRTemp tmpT8 = newTemp(ty);
+               IRTemp tmpT9 = newTemp(ty);
+               assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
+               assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
+               assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
+               assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
+               assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
+               assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
+               assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
+               assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
+               assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
+               assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
+               putIReg(rd, mkexpr(tmpRd));
+               break;
+            }
 
-   /* Spot "Special" instructions (see comment at top of file). */
-   {
-      /* Spot the 16-byte preamble:
-       ****mips32****
-       "srl $0, $0, 13
-       "srl $0, $0, 29
-       "srl $0, $0, 3
-       "srl $0, $0, 19
+            case 0x08 ... 0x0f: { /* DALIGN */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dalign r%u, r%u, r%u, %u", rd, rs, rt, lsb & 0x7);
+                  UInt bp = (lsb & 0x7) << 3;
+
+                  if (bp) {
+                     putIReg(rd, binop(Iop_Or64,
+                                       binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
+                                       binop(Iop_Shr64,
+                                             getIReg(rs), mkU8(64 - bp))));
+                  } else
+                     putIReg(rd, getIReg(rt));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-       ****mips64****
-       dsll $0, $0, 3
-       dsll $0, $0, 13
-       dsll $0, $0, 29
-       dsll $0, $0, 19 */
+               break;
+            }
 
-      UInt word1 = mode64 ? 0xF8  : 0x342;
-      UInt word2 = mode64 ? 0x378 : 0x742;
-      UInt word3 = mode64 ? 0x778 : 0xC2;
-      UInt word4 = mode64 ? 0x4F8 : 0x4C2;
-      if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
-          getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
-         /* Got a "Special" instruction preamble. Which one is it? */
-         if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
-            /* $11 = client_request ( $12 ) */
-            DIP("$11 = client_request ( $12 )");
-            if (mode64)
-               putPC(mkU64(guest_PC_curr_instr + 20));
-            else
-               putPC(mkU32(guest_PC_curr_instr + 20));
-            dres.jk_StopHere = Ijk_ClientReq;
-            dres.whatNext    = Dis_StopHere;
+            case 0: /* DBITSWAP */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dbitswap r%u, r%u", rd, rt);
+                  putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-            goto decode_success;
-         } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
-            /* $11 = guest_NRADDR */
-            DIP("$11 = guest_NRADDR");
-            dres.len = 20;
-            delta += 20;
-            if (mode64)
-               putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
-                                               guest_NRADDR), Ity_I64));
-            else
-               putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
-                                               guest_NRADDR), Ity_I32));
-            goto decode_success;
-         } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
-            /*  branch-and-link-to-noredir $25 */
-            DIP("branch-and-link-to-noredir $25");
-            if (mode64)
-               putIReg(31, mkU64(guest_PC_curr_instr + 20));
-            else
-               putIReg(31, mkU32(guest_PC_curr_instr + 20));
-            putPC(getIReg(25));
-            dres.jk_StopHere = Ijk_NoRedir;
-            dres.whatNext    = Dis_StopHere;
-            goto decode_success;
-         } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
-           /* IR injection */
-            DIP("IR injection");
-#if defined (_MIPSEL)
-            vex_inject_ir(irsb, Iend_LE);
-#elif defined (_MIPSEB)
-            vex_inject_ir(irsb, Iend_BE);
-#endif
-            if (mode64) {
-               stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
-                               mkU64(guest_PC_curr_instr)));
-               stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
-                               mkU64(20)));
+               break;
 
-               putPC(mkU64(guest_PC_curr_instr + 20));
-            } else {
-               stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
-                               mkU32(guest_PC_curr_instr)));
-               stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
-                               mkU32(20)));
+            default:
+               return -1;;
+         }
 
-               putPC(mkU32(guest_PC_curr_instr + 20));
-            }
-            dres.whatNext    = Dis_StopHere;
-            dres.jk_StopHere = Ijk_InvalICache;
-            dres.len = 20;
-            delta += 20;
-            goto decode_success;
+         break;
+
+      case 0x3B: /* RDHWR */
+         DIP("rdhwr r%u, r%u", rt, rd);
+
+         if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+               VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
+               (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
+            if (rd == 29) {
+               putIReg(rt, getULR());
+            } else if (rd <= 3
+                       || (rd == 31
+                           && VEX_MIPS_COMP_ID(archinfo->hwcaps)
+                           == VEX_PRID_COMP_CAVIUM)) {
+               IRExpr** arg = mkIRExprVec_1(mkU32(rd));
+               IRTemp   val  = newTemp(ty);
+               IRDirty *d = unsafeIRDirty_1_N(val,
+                                              0,
+                                              "mips_dirtyhelper_rdhwr",
+                                              &mips_dirtyhelper_rdhwr,
+                                              arg);
+               stmt(IRStmt_Dirty(d));
+               putIReg(rt, mkexpr(val));
+            } else
+               return -1;
+         } else {
+            ILLEGAL_INSTRUCTON
          }
 
-         /* We don't know what it is.  Set opc1/opc2 so decode_failure
-            can print the insn following the Special-insn preamble. */
-         delta += 16;
-         goto decode_failure;
-       /*NOTREACHED*/}
-   }
+         break;
 
-   opcode = get_opcode(cins);
-   imm = get_imm(cins);
-   rs = get_rs(cins);
-   rt = get_rt(cins);
-   rd = get_rd(cins);
-   sa = get_sa(cins);
-   fs = get_fs(cins);
-   fd = get_fd(cins);
-   ft = get_ft(cins);
-   tf = get_tf(cins);
-   nd = get_nd(cins);
-   sel = get_sel(cins);
-   fmt = get_fmt(cins);
-   instr_index = get_instr_index(cins);
-   trap_code = get_code(cins);
-   function = get_function(cins);
-   IRType ty = mode64 ? Ity_I64 : Ity_I32;
-   IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
+      case 0x04:  /* INS */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb - lsb + 1;
+         DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
+
+         vassert(lsb + size <= 32);
+         vassert(lsb + size > 0);
+
+         /* put size bits from rs at the pos in temporary */
+         t0 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         /* shift left for 32 - size to clear leading bits and get zeros
+            at the end */
+         assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
+                          mkU8(32 - size)));
+         /* now set it at pos */
+         t1 = newTemp(Ity_I32);
+         assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
 
-   ac = get_acNo(cins);
+         if (lsb > 0) {
+            t2 = newTemp(Ity_I32);
+            /* clear everything but lower pos bits from rt */
+            assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
+                             mkU8(32 - lsb)));
+            assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
+         } else
+            assign(t3, mkU32(0));
 
-   switch (opcode) {
+         if (msb < 31) {
+            t4 = newTemp(Ity_I32);
+            /* clear everything but upper msb + 1 bits from rt */
+            assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
+                             mkU8(msb + 1)));
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
 
-   case 0x03:     /* JAL */
-      DIP("jal 0x%x", instr_index);
-      if (mode64) {
-         putIReg(31, mkU64(guest_PC_curr_instr + 8));
-         t0 = newTemp(ty);
-         assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
-                          (instr_index << 2)));
-      } else {
-         putIReg(31, mkU32(guest_PC_curr_instr + 8));
-         t0 = newTemp(ty);
-         assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
-                          (instr_index << 2)));
-      }
-      lastn = mkexpr(t0);
-      break;
-   case 0x02:     /* J */
-      DIP("j 0x%x", instr_index);
-      t0 = newTemp(ty);
-      if (mode64)
-         assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
-                          (instr_index << 2)));
-      else
-         assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
-                          (instr_index << 2)));
-      lastn = mkexpr(t0);
-      break;
-
-   case 0x11: {  /* COP1 */
-      if (fmt == 0x3 && fd == 0 && function == 0) {  /* MFHC1 */
-         DIP("mfhc1 r%u, f%u", rt, fs);
-         if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
-             VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            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));
+            /* now combine these registers */
+            if (lsb > 0) {
+               t6 = newTemp(Ity_I32);
+               assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
+               putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
+                                                   mkexpr(t3)), True));
             } else {
-               putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
-                                                  getFReg(fs | 1)), True));
+               putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
+                                                   mkexpr(t5)), True));
             }
          } else {
-            ILLEGAL_INSTRUCTON;
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
+                                                mkexpr(t3)), True));
          }
+
          break;
-      } else if (fmt == 0x7 && fd == 0 && function == 0) {  /* MTHC1 */
-         DIP("mthc1 r%u, f%u", rt, fs);
-         if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
-             VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            if (fp_mode64) {
-               t0 = newTemp(Ity_I64);
-               assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
-                                unop(Iop_ReinterpF32asI32,
-                                     getLoFromF64(Ity_F64, getDReg(fs)))));
-               putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-            } else {
-               putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
-                                    mkNarrowTo32(ty, getIReg(rt))));
-            }
+
+      case 0x00:  /* EXT */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
+         vassert(lsb + size <= 32);
+         vassert(lsb + size > 0);
+
+         /* put size bits from rs at the top of in temporary */
+         if (lsb + size < 32) {
+            t0 = newTemp(Ity_I32);
+            assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
+                             mkU8(32 - lsb - size)));
+
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
+                                                mkU8(32 - size)), True));
          } else {
-            ILLEGAL_INSTRUCTON;
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
+                                                mkNarrowTo32(ty, getIReg(rs)),
+                                                mkU8(32 - size)), True));
          }
+
          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);
 
-         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))));
+      case 0x03:  /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
+         msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
+         t1 = newTemp(Ity_I64);
+         vassert(lsb >= 0 && lsb < 32);
+         vassert(size > 0 && size <= 32);
+         vassert((lsb + size) > 0 && (lsb + size) <= 63);
 
-         if (tf == 1 && nd == 0) {
-            /* branch on true */
-            DIP("bc1t %u, %u", 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 %u, %u", 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 %u, %u", bc1_cc, imm);
-            lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
-                                            mkU32(0x0)), imm);
-            break;
-         } else if (nd == 1 && tf == 1) {
-            DIP("bc1tl %u, %u", bc1_cc, imm);
-            lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
-                                            mkU32(0x0)), imm);
-            break;
-         } else
-            goto decode_failure;
-      } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
-         Int df = fmt & 3;
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_V128);
-         t2 = newTemp(Ity_V128);
-         t3 = newTemp(Ity_V128);
-         assign(t1, getWReg(ft));
-         assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
+         UChar lsAmt = 63 - (lsb + msb);  /* left shift amount; */
+         UChar rsAmt = 63 - msb;  /* right shift amount; */
 
-         switch (df) {
-            case 0x00: { /* BNZ.B */
-                  DIP("BNZ.B w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+         assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+         putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
 
-            case 0x01: { /* BNZ.H */
-                  DIP("BNZ.H w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+         break;
 
-            case 0x02: { /* BNZ.W */
-                  DIP("BNZ.W w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+      case 0x20:  /* BSHFL */
+         switch (sa) {
+            case 0x0: /* BITSWAP */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("bitswap r%u, r%u", rd, rt);
 
-            case 0x03: { /* BNZ.D */
-                  DIP("BNZ.D w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
-                  break;
+                  if (mode64) {
+                     putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
+                                                       mkU8(7), mkU8(8), mkU8(1))));
+                  } else {
+                     putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
+                                     mkU8(8), mkU8(1)));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
                }
-         }
 
-         assign(t0,
-                binop(Iop_Or32,
-                      binop(Iop_Or32,
-                            unop(Iop_V128to32, mkexpr(t3)),
-                            unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
-                      binop(Iop_Or32,
-                            unop(Iop_64to32,
-                                 unop(Iop_V128HIto64, mkexpr(t3))),
-                            unop(Iop_64HIto32,
-                                 unop(Iop_V128HIto64, mkexpr(t3))))));
-         dis_branch(False,
-                    binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
-      } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_V128);
-         assign(t1, getWReg(ft));
-         assign(t0,
-                binop(Iop_Or32,
-                      binop(Iop_Or32,
-                            unop(Iop_V128to32, mkexpr(t1)),
-                            unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
-                      binop(Iop_Or32,
-                            unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
-                            unop(Iop_64HIto32,
-                                 unop(Iop_V128HIto64, mkexpr(t1))))));
-         dis_branch(False,
-                    binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
-      } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
-         Int df = fmt & 3;
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_V128);
-         t2 = newTemp(Ity_V128);
-         t3 = newTemp(Ity_V128);
-         assign(t1, getWReg(ft));
-         assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
+               break;
 
-         switch (df) {
-            case 0x00: { /* BZ.B */
-                  DIP("BZ.B w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+            case 0x02:  /* WSBH */
+               DIP("wsbh r%u, r%u", rd, rt);
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
+                                                 getIReg(rt)), mkU32(0x00FF0000)),
+                                mkU8(0x8)));
+               assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
+                                                 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
+               assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
+                                                 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
+               assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
+                                                 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
+               putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
+                                                   mkexpr(t0), mkexpr(t1)),
+                                                   binop(Iop_Or32, mkexpr(t2),
+                                                         mkexpr(t3))), True));
+               break;
 
-            case 0x01: { /* BZ.H */
-                  DIP("BZ.H w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+            case 0x10:  /* SEB */
+               DIP("seb r%u, r%u", rd, rt);
 
-            case 0x02: { /* BZ.W */
-                  DIP("BZ.W w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
-                  break;
-               }
+               if (mode64)
+                  putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
+               else
+                  putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
 
-            case 0x03: { /* BZ.D */
-                  DIP("BZ.D w%u, %u", ft, imm);
-                  assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
-                  break;
+               break;
+
+            case 0x18:  /* SEH */
+               DIP("seh r%u, r%u", rd, rt);
+
+               if (mode64)
+                  putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
+               else
+                  putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
+
+               break;
+
+            case 0x08 ... 0x0b: /* ALIGN */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  if (mode64) {
+                     UInt bp = (sa & 0x3) << 3;
+
+                     if (bp) {
+                        putIReg(rd, unop(Iop_32Sto64,
+                                         binop(Iop_Or32,
+                                               binop(Iop_Shl32,
+                                                     unop(Iop_64to32,
+                                                          getIReg(rt)),
+                                                     mkU8(bp)),
+                                               binop(Iop_Shr32,
+                                                     unop(Iop_64to32,
+                                                          getIReg(rs)),
+                                                     mkU8(32 - bp)))));
+                     } else
+                        putIReg(rd, getIReg(rt));
+                  } else {
+                     UInt bp = (sa & 0x3) << 3;
+
+                     if (bp) {
+                        putIReg(rd, binop(Iop_Or32,
+                                          binop(Iop_Shl32,
+                                                getIReg(rt), mkU8(bp)),
+                                          binop(Iop_Shr32,
+                                                getIReg(rs), mkU8(32 - bp))));
+                     } else
+                        putIReg(rd, getIReg(rt));
+                  }
+               } else {
+                  ILLEGAL_INSTRUCTON;
                }
+
+               break;
+
+            default:
+               return -1;
+
          }
 
-         assign(t0,
-                binop(Iop_Or32,
-                      binop(Iop_Or32,
-                            unop(Iop_V128to32, mkexpr(t3)),
-                            unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
-                      binop(Iop_Or32,
-                            unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
-                            unop(Iop_64HIto32,
-                                 unop(Iop_V128HIto64, mkexpr(t3))))));
-         dis_branch(False,
-                    binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
-      } else if (fmt == 0x0B && has_msa) { /* BZ.V */
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_V128);
-         assign(t1, getWReg(ft));
-         assign(t0,
-                binop(Iop_Or32,
-                      binop(Iop_Or32,
-                            unop(Iop_V128to32, mkexpr(t1)),
-                            unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
-                      binop(Iop_Or32,
-                            unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
-                            unop(Iop_64HIto32,
-                                 unop(Iop_V128HIto64, mkexpr(t1))))));
-         dis_branch(False,
-                    binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
-      } else if (fmt == 0x09) { /* BC1EQZ */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("bc1eqz f%u, %u", ft, imm);
-            t1 = newTemp(Ity_I1);
-            if (mode64) {
-               assign(t1, binop(Iop_CmpEQ64,
-                                binop(Iop_And64,
-                                      unop(Iop_ReinterpF64asI64, getDReg(ft)),
-                                      mkU64(1)),
-                                mkU64(0)));
-            } else {
-               assign(t1, binop(Iop_CmpEQ32,
-                                binop(Iop_And32,
-                                      unop(Iop_64to32,
-                                           unop(Iop_ReinterpF64asI64, getDReg(ft))),
-                                      mkU32(1)),
-                                mkU32(0)));
-            }
-            dis_branch(False, mkexpr(t1), imm, &bstmt);
-         } else {
-            ILLEGAL_INSTRUCTON;
+         break;  /* BSHFL */
+
+         /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
+      case 0xA:  /* LX */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            if (dis_instr_CVM(cins))
+               break;
+
+            return -1;
          }
-      } else if (fmt == 0x0D) { /* BC1NEZ */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("bc1nez f%u, %u", ft, imm);
-            t1 = newTemp(Ity_I1);
-            if (mode64) {
-               assign(t1, binop(Iop_CmpNE64,
-                                binop(Iop_And64,
-                                      unop(Iop_ReinterpF64asI64, getDReg(ft)),
-                                      mkU64(1)),
-                                mkU64(0)));
-            } else {
-               assign(t1, binop(Iop_CmpNE32,
-                                binop(Iop_And32,
-                                      unop(Iop_64to32,
-                                           unop(Iop_ReinterpF64asI64, getDReg(ft))),
-                                      mkU32(1)),
-                                mkU32(0)));
+         /* fallthrough */
+      case 0xC:  /* INSV */
+      case 0x38: {  /* EXTR.W */
+         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+            if (0 != retVal ) {
+               return -2;
             }
-            dis_branch(False, mkexpr(t1), imm, &bstmt);
+
+            break;
          } else {
-            ILLEGAL_INSTRUCTON;
+            return -2;
          }
-      } else {
-         if (fmt == 0x15) { /* CMP.cond.d */
-            Bool comparison = True;
-            UInt signaling = CMPAFD;
-            DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
-            t0 = newTemp(Ity_I32);
-            /* Conditions starting with S should signal exception on QNaN inputs. */
-            switch (function) {
-               case 8:  /* SAF */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0: /* AF */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          binop(Iop_I64StoF64,
-                                get_IR_roundingmode(), mkU64(0)));
-                  break;
-               case 9: /* SUN */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 1: /* UN */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0))));
-                  break;
-               case 0x19: /* SOR */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x11: /* OR */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL))));
-                  break;
-               case 0xa: /* SEQ */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 2: /* EQ */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0))));
-                  break;
-               case 0x1A: /* SNEQ */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x12: /* NEQ */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL))));
-                  break;
-               case 0xB: /* SUEQ */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x3: /* UEQ */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0), mkU32(0x45)),
-                                                unop(Iop_ReinterpI64asF64,
-                                                     mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                                binop(Iop_I64StoF64,
-                                                      get_IR_roundingmode(),
-                                                      mkU64(0)))));
-                  break;
-               case 0x1B:  /* SNEQ */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x13:  /* NEQ */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0),mkU32(0x00)),
-                                                unop(Iop_ReinterpI64asF64,
-                                                     mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                                binop(Iop_I64StoF64,
-                                                      get_IR_roundingmode(),
-                                                      mkU64(0)))));
-                  break;
-               case 0xC: /* SLT */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x4: /* LT */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0))));
-                  break;
-               case 0xD: /* SULT */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x5: /* ULT */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                    IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                     mkexpr(t0), mkU32(0x45)),
-                                               unop(Iop_ReinterpI64asF64,
-                                                    mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                               binop(Iop_I64StoF64,
-                                                     get_IR_roundingmode(),
-                                                     mkU64(0)))));
-                  break;
-               case 0xE: /* SLE */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x6: /* LE */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0),mkU32(0x40)),
-                                                unop(Iop_ReinterpI64asF64,
-                                                     mkU64(0xFFFFFFFFFFFFFFFFULL)),
-                                                binop(Iop_I64StoF64,
-                                                      get_IR_roundingmode(),
-                                                      mkU64(0)))));
-                  break;
-               case 0xF: /* SULE */
-                  signaling = CMPSAFD; /* fallthrough */
-               case 0x7: /* ULE */
-                  assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
-                  calculateFCSR(fs, ft, signaling, False, 2);
-                  putDReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
-                                     binop(Iop_I64StoF64,
-                                           get_IR_roundingmode(), mkU64(0)),
-                                     unop(Iop_ReinterpI64asF64,
-                                          mkU64(0xFFFFFFFFFFFFFFFFULL))));
+
+         break;
+      }
+
+      case 0x10: {  /* ADDU.QB */
+         switch (sa) {
+            case  0xC:  /* SUBU_S.PH */
+            case  0xD:  /* ADDU_S.PH */
+            case 0x1E: {  /* MULQ_S.PH */
+               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+                  if (0 != retVal ) {
+                     return -2;
+                  }
+
                   break;
-               default:
-                  comparison = False;
-            }
-            if (comparison) {
-               if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
+               } else {
+                  return -2;
                }
+
                break;
             }
 
-         } else if (fmt == 0x14) {
-            Bool comparison = True;
-            UInt signaling = CMPAFS;
-            DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
-            t0 = newTemp(Ity_I32);
-            /* Conditions starting with S should signal exception on QNaN inputs. */
-            switch (function) {
-               case 8:  /* SAF */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0: /* AF */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         binop(Iop_I32StoF32,
-                                               get_IR_roundingmode(), mkU32(0))));
-                  break;
-               case 9: /* SUN */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 1: /* UN */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                         mkU32(0xFFFFFFFFU))),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0)))));
-                  break;
-               case 0x19: /* SOR */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x11: /* OR */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0))),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                    mkU32(0xFFFFFFFFU)))));
-                  break;
-               case 0xa: /* SEQ */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 2: /* EQ */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                         mkU32(0xFFFFFFFFU))),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0)))));
-                  break;
-               case 0x1A: /* SNEQ */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x12: /* NEQ */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0))),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                         mkU32(0xFFFFFFFFU)))));
-                  break;
-               case 0xB: /* SUEQ */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x3: /* UEQ */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                         mkU32(0xFFFFFFFFU))),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0), mkU32(0x45)),
-                                                mkWidenFromF32(tyF,
-                                                               unop(Iop_ReinterpI32asF32,
-                                                               mkU32(0xFFFFFFFFU))),
-                                                mkWidenFromF32(tyF,
-                                                               binop(Iop_I32StoF32,
-                                                                     get_IR_roundingmode(),
-                                                                     mkU32(0))))));
-                  break;
-               case 0x1B:  /* SNEQ */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x13:  /* NEQ */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                    mkU32(0xFFFFFFFFU))),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0),mkU32(0x00)),
-                                                mkWidenFromF32(tyF,
-                                                               unop(Iop_ReinterpI32asF32,
-                                                                    mkU32(0xFFFFFFFFU))),
-                                                mkWidenFromF32(tyF,
-                                                               binop(Iop_I32StoF32,
-                                                                     get_IR_roundingmode(),
-                                                                     mkU32(0))))));
-                  break;
-               case 0xC: /* SLT */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x4: /* LT */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                         mkU32(0xFFFFFFFFU))),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0)))));
-                  break;
-               case 0xD: /* SULT */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x5: /* ULT */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                    mkU32(0xFFFFFFFFU))),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0), mkU32(0x45)),
-                                                mkWidenFromF32(tyF,
-                                                               unop(Iop_ReinterpI32asF32,
-                                                                    mkU32(0xFFFFFFFFU))),
-                                                mkWidenFromF32(tyF,
-                                                               binop(Iop_I32StoF32,
-                                                                     get_IR_roundingmode(),
-                                                                     mkU32(0))))));
-                  break;
-               case 0xE: /* SLE */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x6: /* LE */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                    mkU32(0xFFFFFFFFU))),
-                                     IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                      mkexpr(t0),mkU32(0x40)),
-                                                mkWidenFromF32(tyF,
-                                                               unop(Iop_ReinterpI32asF32,
-                                                               mkU32(0xFFFFFFFFU))),
-                                                mkWidenFromF32(tyF,
-                                                               binop(Iop_I32StoF32,
-                                                                     get_IR_roundingmode(),
-                                                                     mkU32(0))))));
-                  break;
-               case 0xF: /* SULE */
-                  signaling = CMPSAFS; /* fallthrough */
-               case 0x7: /* ULE */
-                  assign(t0, binop(Iop_CmpF32,
-                                   getLoFromF64(Ity_F64, getFReg(fs)),
-                                   getLoFromF64(Ity_F64, getFReg(ft))));
-                  calculateFCSR(fs, ft, signaling, True, 2);
-                  putFReg(fd,
-                          IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
-                                     mkWidenFromF32(tyF,
-                                                    binop(Iop_I32StoF32,
-                                                          get_IR_roundingmode(),
-                                                          mkU32(0))),
-                                     mkWidenFromF32(tyF,
-                                                    unop(Iop_ReinterpI32asF32,
-                                                    mkU32(0xFFFFFFFFU)))));
+            default: {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+                  if (0 != retVal ) {
+                     return -2;
+                  }
+
                   break;
-               default:
-                  comparison = False;
-            }
-            if (comparison) {
-               if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
+               } else {
+                  return -2;
                }
+
                break;
             }
          }
 
-         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)));
-                     break;
-                  }
-                  default:
-                     goto decode_failure;
+         break;
+      }
+
+      case 0x11: {  /* CMPU.EQ.QB */
+         switch (sa) {
+            case 0x18:  /* CMPGDU.EQ.QB */
+            case 0x19:  /* CMPGDU.LT.QB */
+            case 0x1A:  /* CMPGDU.LE.QB */
+            case 0x0D:  /* PRECR.QB.PH */
+            case 0x1E:  /* PRECR_SRA.PH.W */
+            case 0x1F: {  /* PRECR_SRA_R.PH.W */
+               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+                  if (0 != retVal ) {
+                     return -2;
                   }
+
+                  break;
+               } else {
+                  return -2;
                }
+
                break;
-            case 0x5:  /* abs.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("abs.s f%u, f%u", fd, fs);
-                     putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
-                                 getLoFromF64(tyF, getFReg(fs)))));
-                     break;
-                  case 0x11:  /* D  */
-                     DIP("abs.d f%u, f%u", 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 */
-                     DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
-                                       getDReg(ft)));
-                     break;
-                  }
-                  case 0x10: {  /* S */
-                     DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
-                                 getLoFromF64(tyF, getFReg(fs)),
-                                 getLoFromF64(tyF, getFReg(ft)))));
-                     break;
-                  }
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* MUL.fmt */
-
-            case 0x03:  /* DIV.fmt */
-               switch (fmt) {
-                  case 0x11: {  /* D */
-                     DIP("div.d f%u, f%u, f%u", fd, fs, ft);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
-                                 getDReg(ft)));
-                     break;
-                  }
-                  case 0x10: {  /* S */
-                     DIP("div.s f%u, f%u, f%u", fd, fs, ft);
-                     calculateFCSR(fs, ft, DIVS, False, 2);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
-                                 getLoFromF64(tyF, getFReg(fs)),
-                                 getLoFromF64(tyF, getFReg(ft)))));
-                     break;
-                  }
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* DIV.fmt */
-
-            case 0x01:  /* SUB.fmt */
-               switch (fmt) {
-                  case 0x11: {  /* D */
-                     DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
-                     calculateFCSR(fs, ft, SUBD, False, 2);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
-                                       getDReg(ft)));
-                     break;
-                  }
-                  case 0x10: {  /* S */
-                     DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
-                     calculateFCSR(fs, ft, SUBS, True, 2);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
-                                 getLoFromF64(tyF, getFReg(fs)),
-                                 getLoFromF64(tyF, getFReg(ft)))));
-                     break;
+            }
+
+            default: {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+                  if (0 != retVal ) {
+                     return -2;
                   }
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* SUB.fmt */
-
-            case 0x06:  /* MOV.fmt */
-               switch (fmt) {
-                  case 0x11:  /* D */
-                     DIP("mov.d f%u, f%u", fd, fs);
-                     if (fp_mode64) {
-                        putDReg(fd, getDReg(fs));
-                     } else {
-                        putFReg(fd, getFReg(fs));
-                        putFReg(fd + 1, getFReg(fs + 1));
-                     }
-                     break;
-                  case 0x10:  /* S */
-                     DIP("mov.s f%u, f%u", fd, fs);
-                     putFReg(fd, getFReg(fs));
-                     break;
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* MOV.fmt */
-
-            case 0x7:  /* neg.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("neg.s f%u, f%u", fd, fs);
-                     putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
-                                 getLoFromF64(tyF, getFReg(fs)))));
-                     break;
-                  case 0x11:  /* D */
-                     DIP("neg.d f%u, f%u", fd, fs);
-                     putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
-                     break;
-                  default:
-                     goto decode_failure;
+
+                  break;
+               } else {
+                  return -2;
                }
-               break;  /* case 0x7 */
 
-            case 0x08:  /* ROUND.L.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("round.l.s f%u, f%u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, ROUNDLS, True, 1);
-                        t0 = newTemp(Ity_I64);
+               break;
+            }
+         }
 
-                        assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
-                                         getLoFromF64(Ity_F64, getFReg(fs))));
+         break;
+      }
 
-                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  case 0x11:  /* D */
-                     DIP("round.l.d f%u, f%u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, ROUNDLD, False, 1);
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         binop(Iop_F64toI64S,
-                                               mkU32(0x0),
-                                               getDReg(fs))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  default:
-                    goto decode_failure;
+      case 0x12: {  /* ABSQ_S.PH */
+         switch (sa) {
+            case 0x1: {  /* ABSQ_S.QB */
+               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-               }
-               break;  /* ROUND.L.fmt */
-
-            case 0x09:  /* TRUNC.L.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("trunc.l.s f%u, f%u", fd, 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))));
-
-                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  case 0x11:  /* D */
-                     DIP("trunc.l.d f%u, f%u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, TRUNCLD, False, 1);
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         binop(Iop_F64toI64S,
-                                               mkU32(0x3),
-                                               getDReg(fs))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  default:
-                     goto decode_failure;
-                 }
-              break;  /* TRUNC.L.fmt */
-
-            case 0x15:  /* RECIP.fmt */
-               switch (fmt) {
-                  case 0x10: {  /* S */
-                     DIP("recip.s f%u, f%u", fd, fs);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
-                                 rm, unop(Iop_ReinterpI32asF32,
-                                 mkU32(ONE_SINGLE)), getLoFromF64(tyF,
-                                 getFReg(fs)))));
-                     break;
-                  }
-                  case 0x11: {  /* D */
-                     DIP("recip.d f%u, f%u", fd, fs);
-                     IRExpr *rm = get_IR_roundingmode();
-                     /* putDReg(fd, 1.0/getDreg(fs)); */
-                     putDReg(fd, triop(Iop_DivF64, rm,
-                                 unop(Iop_ReinterpI64asF64,
-                                 mkU64(ONE_DOUBLE)), getDReg(fs)));
-                     break;
+                  if (0 != retVal ) {
+                     return -2;
                   }
-               default:
-                  goto decode_failure;
 
+                  break;
+               } else {
+                  return -2;
                }
-               break;  /* case 0x15 */
-
-            case 0x13:  /* MOVN.fmt */
-               switch (fmt) {
-               case 0x10:  /* S */
-                  DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
-                  t1 = newTemp(Ity_I1);
 
-                  if (mode64)
-                     assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
-                  else
-                     assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
+               break;
+            }
 
-                  putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
-                  break;
-               case 0x11:  /* D */
-                  DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
-                  t1 = newTemp(Ity_I1);
+            default: {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                  if (mode64)
-                     assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
-                  else
-                     assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
+                  if (0 != retVal ) {
+                     return -2;
+                  }
 
-                  putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
                   break;
-               default:
-                  goto decode_failure;
+               } else {
+                  return -2;
                }
-               break;  /* MOVN.fmt */
 
-            case 0x12:  /* MOVZ.fmt */
-               switch (fmt) {
-               case 0x10:  /* S */
-                  DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
-                  t1 = newTemp(Ity_I1);
+               break;
+            }
+         }
 
-                  if (mode64)
-                     assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
-                  else
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
+         break;
+      }
 
-                  putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
-                  break;
-               case 0x11:  /* D */
-                  DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
-                  t1 = newTemp(Ity_I1);
+      case 0x13: {  /* SHLL.QB */
+         switch (sa) {
+            case 0x04:  /* SHRA.QB */
+            case 0x05:  /* SHRA_R.QB */
+            case 0x06:  /* SHRAV.QB */
+            case 0x07:  /* SHRAV_R.QB */
+            case 0x19:  /* SHLR.PH */
+            case 0x1B: {  /* SHLRV.PH */
+               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                  if (mode64)
-                     assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
-                  else
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
+                  if (0 != retVal ) {
+                     return -2;
+                  }
 
-                  putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
                   break;
-               default:
-                  goto decode_failure;
+               } else {
+                  return -2;
                }
-               break;  /* MOVZ.fmt */
-
-            case 0x11:  /* MOVT.fmt */
-               if (tf == 1) {
-                  UInt mov_cc = get_mov_cc(cins);
-                  switch (fmt) {  /* MOVCF = 010001 */
-                  case 0x11:  /* D */
-                     DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_F64);
-
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                                 mkU32(0x1))
-                                           ));
-
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
-                     assign(t4, IRExpr_ITE(mkexpr(t3),
-                                           getDReg(fs), getDReg(fd)));
-                     putDReg(fd, mkexpr(t4));
-                     break;
-                  case 0x10:  /* S */
-                     DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_F64);
-                     t5 = newTemp(Ity_F64);
-                     t6 = newTemp(Ity_F64);
-                     t7 = newTemp(Ity_I64);
-
-                     if (fp_mode64) {
-                        assign(t5, getFReg(fs));
-                        assign(t6, getFReg(fd));
-                     } else {
-                        assign(t5, unop(Iop_F32toF64, getFReg(fs)));
-                        assign(t6, unop(Iop_F32toF64, getFReg(fd)));
-                     }
 
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                                 mkU32(0x1))
-                                           ));
-
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
-                     assign(t4, IRExpr_ITE(mkexpr(t3),
-                                           mkexpr(t5), mkexpr(t6)));
-
-                     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(Ity_I64, unop(Iop_64to32,
-                                      unop(Iop_ReinterpF64asI64, mkexpr(t4))),
-                                      True));
+               break;
+            }
 
-                        putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
-                     } else
-                        putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                          mkexpr(t4)));
-                     break;
-                  default:
-                     goto decode_failure;
-                  }
-               } else if (tf == 0)  /* movf.fmt */
-               {
-                  UInt mov_cc = get_mov_cc(cins);
-                  switch (fmt)  /* MOVCF = 010001 */
-                  {
-                  case 0x11:  /* D */
-                     DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_F64);
-
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                                 mkU32(0x1))
-                                           ));
-
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
-                     assign(t4, IRExpr_ITE(mkexpr(t3),
-                                           getDReg(fs), getDReg(fd)));
-                     putDReg(fd, mkexpr(t4));
-                     break;
-                  case 0x10:  /* S */
-                     DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
-                     t1 = newTemp(Ity_I1);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_F64);
-                     t5 = newTemp(Ity_F64);
-                     t6 = newTemp(Ity_F64);
-
-                     if (fp_mode64) {
-                        assign(t5, getFReg(fs));
-                        assign(t6, getFReg(fd));
-                     } else {
-                        assign(t5, unop(Iop_F32toF64, getFReg(fs)));
-                        assign(t6, unop(Iop_F32toF64, getFReg(fd)));
-                     }
+            default: {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                     assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                                 mkU32(0x1))
-                                           ));
-
-                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
-                     assign(t4, IRExpr_ITE(mkexpr(t3),
-                                           mkexpr(t5), mkexpr(t6)));
-
-                     if (fp_mode64) {
-                        IRTemp f = newTemp(Ity_F64);
-                        IRTemp fd_hi = newTemp(Ity_I32);
-                        t7 = newTemp(Ity_I64);
-                        assign(f, getFReg(fd));
-                        assign(fd_hi, unop(Iop_64HIto32,
-                                      unop(Iop_ReinterpF64asI64, mkexpr(f))));
-                        assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
-                                   unop(Iop_ReinterpF64asI64, mkexpr(t4))),
-                                   True));
-
-                        putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
-                     } else
-                        putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                          mkexpr(t4)));
-                     break;
-                  default:
-                     goto decode_failure;
+                  if (0 != retVal ) {
+                     return -2;
                   }
-               }
 
-               break;  /* MOVT.fmt */
-
-            case 0x0:  /* add.fmt */
-               switch (fmt) {
-               case 0x10: {  /* S */
-                  DIP("add.s f%u, f%u, f%u", fd, fs, ft);
-                  calculateFCSR(fs, ft, ADDS, True, 2);
-                  IRExpr *rm = get_IR_roundingmode();
-                  putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
-                              getLoFromF64(tyF, getFReg(fs)),
-                              getLoFromF64(tyF, getFReg(ft)))));
-                  break;
-               }
-               case 0x11: {  /* D */
-                  DIP("add.d f%u, f%u, f%u", fd, fs, ft);
-                  calculateFCSR(fs, ft, ADDD, False, 2);
-                  IRExpr *rm = get_IR_roundingmode();
-                  putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
                   break;
+               } else {
+                  return -2;
                }
 
-               case 0x4:  /* MTC1 (Move Word to Floating Point) */
-                  DIP("mtc1 r%u, f%u", rt, fs);
-                  if (fp_mode64) {
-                     t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_F32);
-                     assign(t0, mkNarrowTo32(ty, getIReg(rt)));
-                     assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+               break;
+            }
+         }
 
-                     putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
-                  } else
-                     putFReg(fs, unop(Iop_ReinterpI32asF32,
-                                      mkNarrowTo32(ty, getIReg(rt))));
-                  break;
+         break;
+      }
 
-               case 0x5:  /* Doubleword Move to Floating Point DMTC1; MIPS64 */
-                  DIP("dmtc1 r%u, f%u", rt, fs);
-                  vassert(mode64);
-                  putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
-                  break;
+      case 0x30: {  /* DPAQ.W.PH */
+         switch (sa) {
+            case  0x0:  /* DPA.W.PH */
+            case 0x18:  /* DPAQX_S.W.PH */
+            case 0x1A:  /* DPAQX_SA.W.PH */
+            case  0x8:  /* DPAX.W.PH */
+            case  0x1:  /* DPS.W.PH */
+            case 0x19:  /* DPSQX_S.W.PH */
+            case 0x1B:  /* DPSQX_SA.W.PH */
+            case  0x9:  /* DPSX.W.PH */
+            case  0x2: {  /* MULSA.W.PH */
+               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-               case 0x0:  /* MFC1 */
-                  DIP("mfc1 r%u, f%u", rt, fs);
-                  if (fp_mode64) {
-                     t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I32);
-                     assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
-                     assign(t1, unop(Iop_64to32, mkexpr(t0)));
-                     putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
-                  } else
-                     putIReg(rt, mkWidenFrom32(ty,
-                                 unop(Iop_ReinterpF32asI32, getFReg(fs)),
-                                 True));
-                  break;
+                  if (0 != retVal ) {
+                     return -2;
+                  }
 
-               case 0x1:  /* Doubleword Move from Floating Point DMFC1;
-                             MIPS64 */
-                  DIP("dmfc1 r%u, f%u", rt, fs);
-                  putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
                   break;
+               } else {
+                  return -2;
+               }
 
-               case 0x6:  /* CTC1 */
-                  DIP("ctc1 r%u, f%u", rt, fs);
-                  t0 = newTemp(Ity_I32);
-                  t1 = newTemp(Ity_I32);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I32);
-                  t4 = newTemp(Ity_I32);
-                  t5 = newTemp(Ity_I32);
-                  t6 = newTemp(Ity_I32);
-                  assign(t0, mkNarrowTo32(ty, getIReg(rt)));
-                  if (fs == 25) {  /* FCCR */
-                     assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x000000FE)), mkU8(24)));
-                     assign(t2, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x01000000)));
-                     assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x00000001)), mkU8(23)));
-                     assign(t4, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x007FFFFF)));
-                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
-                                   mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
-                                   mkexpr(t4))));
-                  } else if (fs == 26) {  /* FEXR */
-                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
-                     assign(t2, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x0003F000)));
-                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
-                     assign(t4, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x0000007C)));
-                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
-                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
-                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
-                                   mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
-                  } else if (fs == 28) {
-                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
-                     assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
-                                mkU32(0x00000002)), mkU8(22)));
-                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
-                     assign(t4, binop(Iop_And32, mkexpr(t0),
-                                mkU32(0x00000F80)));
-                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
-                     assign(t6, binop(Iop_And32, mkexpr(t0),
-                                mkU32(0x00000003)));
-                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
-                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
-                                   mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
-                                   mkexpr(t5), mkexpr(t6))));
-                  } else if (fs == 31) {
-                     putFCSR(mkexpr(t0));
-                  }
-                  break;
-               case 0x2:  /* CFC1 */
-                  DIP("cfc1 r%u, f%u", rt, fs);
-                  t0 = newTemp(Ity_I32);
-                  t1 = newTemp(Ity_I32);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I32);
-                  t4 = newTemp(Ity_I32);
-                  t5 = newTemp(Ity_I32);
-                  t6 = newTemp(Ity_I32);
-                  assign(t0, getFCSR());
-                  if (fs == 0) {
-                     putIReg(rt, mkWidenFrom32(ty,
-                             IRExpr_Get(offsetof(VexGuestMIPS32State,
-                                                 guest_FIR),
-                                       Ity_I32),
-                             False));
-                  } else if (fs == 25) {
-                     assign(t1, mkU32(0x000000FF));
-                     assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0xFE000000)), mkU8(25)));
-                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x00800000)), mkU8(23)));
-                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
-                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
-                                 mkexpr(t3)), False));
-                  } else if (fs == 26) {
-                     assign(t1, mkU32(0xFFFFF07C));
-                     assign(t2, binop(Iop_And32, mkexpr(t0),
-                                mkU32(0x0003F000)));
-                     assign(t3, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x0000007C)));
-                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
-                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
-                                 mkexpr(t3)), False));
-                  } else if (fs == 28) {
-                     assign(t1, mkU32(0x00000F87));
-                     assign(t2, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x00000F83)));
-                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
-                                      mkU32(0x01000000)), mkU8(22)));
-                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
-                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
-                                 mkexpr(t3)), False));
-                  } else if (fs == 31) {
-                     putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
+               break;
+            }
+
+            default: {
+               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+                  if (0 != retVal ) {
+                     return -2;
                   }
+
                   break;
-               default:
-                  goto decode_failure;
+               } else {
+                  return -2;
                }
-               break;
 
-            case 0x21:  /* CVT.D */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("cvt.d.s f%u, f%u", fd, fs);
-                     calculateFCSR(fs, 0, CVTDS, True, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I64);
-                        t1 = newTemp(Ity_I32);
-                        t3 = newTemp(Ity_F32);
-                        t4 = newTemp(Ity_F32);
-                        /* get lo half of FPR */
-                        assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+               break;
+            }
+         }
 
-                        assign(t1, unop(Iop_64to32, mkexpr(t0)));
+         break;
+      }
 
-                        assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
+      case 0x18:  /* ADDUH.QB/MUL.PH */
+      case 0x31: {  /* APPEND */
+         if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
 
-                        putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
-                     } else
-                        putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
-                     break;
+            if (0 != retVal ) {
+               return -2;
+            }
 
-                  case 0x14:
-                     DIP("cvt.d.w %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, CVTDW, True, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I64);
-                        t1 = newTemp(Ity_I32);
-                        t3 = newTemp(Ity_F32);
-                        t4 = newTemp(Ity_F32);
-                        /* get lo half of FPR */
-                        assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+            break;
+         } else {
+            return -2;
+         }
+      }
 
-                        assign(t1, unop(Iop_64to32, mkexpr(t0)));
-                        putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1)));
-                        break;
-                     } else {
-                        t0 = newTemp(Ity_I32);
-                        assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
-                        putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
-                        break;
-                     }
+      case 0x35: { /* PREF r6*/
+         DIP("pref");
+         break;
+      }
 
-                  case 0x15: {  /* L */
-                     if (fp_mode64) {
-                        DIP("cvt.d.l %u, %u", fd, fs);
-                        calculateFCSR(fs, 0, CVTDL, False, 1);
-                        t0 = newTemp(Ity_I64);
-                        assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+      case 0x36: { /* LL */
+         imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+         DIP("ll r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         t2 = newTemp(ty);
+         assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+         putLLaddr(mkexpr(t1));
+         putLLdata(mkexpr(t2));
+         putIReg(rt, mkexpr(t2));
+         break;
+      }
 
-                        putFReg(fd, binop(Iop_I64StoF64,
-                                          get_IR_roundingmode(), mkexpr(t0)));
-                        break;
-                     } else
-                        goto decode_failure;
-                  }
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* CVT.D */
-
-            case 0x20:  /* cvt.s */
-               switch (fmt) {
-                  case 0x14:  /* W */
-                     DIP("cvt.s.w %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, CVTSW, True, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I64);
-                        t1 = newTemp(Ity_I32);
-                        t3 = newTemp(Ity_F32);
-                        t4 = newTemp(Ity_F32);
-                        /* get lo half of FPR */
-                        assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
-
-                        assign(t1, unop(Iop_64to32, mkexpr(t0)));
-                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
-                                    get_IR_roundingmode(), mkexpr(t1))));
-                     } else {
-                        t0 = newTemp(Ity_I32);
-                        assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
-                        putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
-                                    mkexpr(t0)));
-                     }
-                     break;
+      case 0x26: { /* SC */
+         imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+         DIP("sc r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
 
-                  case 0x11:  /* D */
-                     DIP("cvt.s.d %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, CVTSD, False, 1);
-                     t0 = newTemp(Ity_F32);
-                     assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
-                                      getDReg(fs)));
-                     putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
-                     break;
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I32);
+         assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                          mkexpr(t1), getLLaddr()));
+         assign(t3, mkNarrowTo32(ty, getIReg(rt)));
+         putLLaddr(LLADDR_INVALID);
+         putIReg(rt, getIReg(0));
 
-                  case 0x15:  /* L */
-                     DIP("cvt.s.l %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, CVTSL, False, 1);
-                        t0 = newTemp(Ity_I64);
-                        assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+         mips_next_insn_if(mkexpr(t2));
 
-                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
-                                    get_IR_roundingmode(), mkexpr(t0))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
 
-                  default:
-                     goto decode_failure;
-               }
-               break;  /* cvt.s */
-
-            case 0x24:  /* cvt.w */
-               switch (fmt) {
-               case 0x10:  /* S */
-                  DIP("cvt.w.s %u, %u", fd, fs);
-                  calculateFCSR(fs, 0, CVTWS, True, 1);
-                  putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         unop(Iop_ReinterpI32asF32,
-                                              binop(Iop_F32toI32S,
-                                                    get_IR_roundingmode(),
-                                                    getLoFromF64(tyF,
-                                                                 getFReg(fs))))));
-                  break;
+         assign(t5, mkNarrowTo32(ty, getLLdata()));
 
-               case 0x11:
-                  DIP("cvt.w.d %u, %u", fd, fs);
-                  calculateFCSR(fs, 0, CVTWD, False, 1);
-                  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;
+         stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+                                 MIPS_IEND, mkexpr(t1),                 /* addr */
+                                 NULL, mkexpr(t5),                      /* expected value */
+                                 NULL, mkexpr(t3)                       /* new value */)));
 
-               default:
-                  goto decode_failure;
+         putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
+                          binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
+         break;
+      }
 
-               }
-               break;
+      case 0x37: { /* LLD */
+         imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+         DIP("lld r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
 
-            case 0x25:  /* cvt.l */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("cvt.l.s %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, CVTLS, True, 1);
-                        t0 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         assign(t2, load(Ity_I64, mkexpr(t1)));
+         putLLaddr(mkexpr(t1));
+         putLLdata(mkexpr(t2));
+         putIReg(rt, mkexpr(t2));
+         break;
+      }
 
-                        assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
-                                         getLoFromF64(tyF, getFReg(fs))));
+      case 0x27: { /* SCD */
+         imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+         DIP("sdc r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
 
-                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I64);
+         assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
+         assign(t3, getIReg(rt));
+         putLLaddr(LLADDR_INVALID);
+         putIReg(rt, getIReg(0));
 
-                  case 0x11: {  /* D */
-                     DIP("cvt.l.d %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, CVTLD, False, 1);
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         binop(Iop_F64toI64S,
-                                               get_IR_roundingmode(),
-                                               getDReg(fs))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  }
+         mips_next_insn_if(mkexpr(t2));
 
-                  default:
-                     goto decode_failure;
-               }
-               break;
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
 
-            case 0x0B:  /* FLOOR.L.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("floor.l.s %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, FLOORLS, True, 1);
-                        t0 = newTemp(Ity_I64);
+         assign(t5, getLLdata());
 
-                        assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
-                                         getLoFromF64(tyF, getFReg(fs))));
+         stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+                                 MIPS_IEND, mkexpr(t1),                 /* addr */
+                                 NULL, mkexpr(t5),                      /* expected value */
+                                 NULL, mkexpr(t3)                       /* new value */)));
 
-                        putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
+         putIReg(rt, unop(Iop_1Uto64,
+                          binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
+         break;
+      }
 
-                  case 0x11:  /* D */
-                     DIP("floor.l.d %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, FLOORLD, False, 1);
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         binop(Iop_F64toI64S,
-                                               mkU32(0x01),
-                                               getDReg(fs))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
-                  default:
-                     goto decode_failure;
-               }
-               break;
+      default:
+         return -1;
+   }
 
-            case 0x0C:  /* ROUND.W.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("round.w.s f%u, f%u", fd, fs);
-                     calculateFCSR(fs, 0, ROUNDWS, True, 1);
-                     putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         unop(Iop_ReinterpI32asF32,
-                                              binop(Iop_F32toI32S,
-                                                    mkU32(0x0),
-                                                    getLoFromF64(tyF,
-                                                                 getFReg(fs))))));
-                     break;
+   return 0;
+}
 
-                  case 0x11:  /* D */
-                     DIP("round.w.d f%u, f%u", fd, fs);
-                     calculateFCSR(fs, 0, ROUNDWD, False, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I32);
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
-                                         getDReg(fs)));
-                        putFReg(fd, mkWidenFromF32(tyF,
-                                    unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                     } else {
-                        t0 = newTemp(Ity_I32);
+static UInt disInstr_MIPS_WRK_00(UInt cins, const VexArchInfo* archinfo,
+                                 const VexAbiInfo*  abiinfo, DisResult* dres,
+                                 IRStmt** bstmt, IRExpr** lastn,
+                                 Bool(*resteerOkFn) (/*opaque */void *,
+                                       Addr),
+                                 void*        callback_opaque)
+{
+   IRTemp t0;
+   UInt opcode, rs, rt, trap_code, imm, instr_index, p;
+   /* Additional variables for instruction fields in DSP ASE insructions */
 
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
-                                         getDReg(fs)));
+   opcode = get_opcode(cins);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   instr_index = get_instr_index(cins);
+   trap_code = get_code(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
 
-                        putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                     }
-                     break;
-                  default:
-                     goto decode_failure;
+   switch (opcode & 0x0F) {
+      case 0x00:  /* Special */
+         return disInstr_MIPS_WRK_Special(cins, archinfo, abiinfo, dres, bstmt, lastn,
+                                          resteerOkFn, callback_opaque);
 
-                  }
-                  break;  /* ROUND.W.fmt */
+      case 0x01:  /* Regimm */
+         switch (rt) {
+            case 0x00:  /* BLTZ */
+               DIP("bltz r%u, %u", rs, imm);
 
-            case 0x0F:  /* FLOOR.W.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("floor.w.s f%u, f%u", fd, fs);
-                     calculateFCSR(fs, 0, FLOORWS, True, 1);
-                     putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         unop(Iop_ReinterpI32asF32,
-                                              binop(Iop_F32toI32S,
-                                                    mkU32(0x1),
-                                                    getLoFromF64(tyF,
-                                                                 getFReg(fs))))));
-                     break;
+               if (mode64) {
+                  if (!dis_instr_branch(cins, dres, resteerOkFn,
+                                        callback_opaque, bstmt))
+                     return -1;
+               } else
+                  dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                                          mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
 
-                  case 0x11:  /* D */
-                     DIP("floor.w.d f%u, f%u", fd, fs);
-                     calculateFCSR(fs, 0, FLOORWD, False, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I32);
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
-                                         getDReg(fs)));
-                        putFReg(fd, mkWidenFromF32(tyF,
-                                    unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                        break;
-                     } else {
-                        t0 = newTemp(Ity_I32);
+               break;
 
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
-                                         getDReg(fs)));
+            case 0x01:  /* BGEZ */
+               DIP("bgez r%u, %u", rs, imm);
 
-                        putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                        break;
-                     }
-                  default:
-                     goto decode_failure;
+               if (mode64) {
+                  if (!dis_instr_branch(cins, dres, resteerOkFn,
+                                        callback_opaque, bstmt))
+                     return -1;
+               } else
+                  dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                                          mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
 
-               }
-               break;  /* FLOOR.W.fmt */
+               break;
 
-            case 0x0D:  /* TRUNC.W */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("trunc.w.s %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, TRUNCWS, True, 1);
-                     putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         unop(Iop_ReinterpI32asF32,
-                                              binop(Iop_F32toI32S,
-                                                    mkU32(0x3),
-                                                    getLoFromF64(tyF,
-                                                                 getFReg(fs))))));
-                     break;
-                  case 0x11:  /* D */
-                     DIP("trunc.w.d %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, TRUNCWD, False, 1);
-                     if (fp_mode64) {
-                        t0 = newTemp(Ity_I32);
+            case 0x02:  /* BLTZL */
+               DIP("bltzl r%u, %u", rs, imm);
+               *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                                                binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+                                                      mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+                                                mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+                                          imm);
+               break;
 
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
-                                         getFReg(fs)));
+            case 0x03:  /* BGEZL */
+               DIP("bgezl r%u, %u", rs, imm);
+               *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                                                binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+                                                      mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+                                                mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
+               break;
 
-                        putFReg(fd, mkWidenFromF32(tyF,
-                                    unop(Iop_ReinterpI32asF32, mkexpr(t0))));
-                     } else {
-                        t0 = newTemp(Ity_I32);
+            case 0x06: { /* DAHI */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dahi  r%u,  %x", rs, imm);
+                  putIReg(rs, binop(Iop_Add64,
+                                    getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
+               } else {
+                  ILLEGAL_INSTRUCTON
+               }
 
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
-                                         getDReg(fs)));
+               break;
+            }
 
-                        putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                     }
-                     break;
-                  default:
-                     goto decode_failure;
+            case 0x08:  /* TGEI */
+               DIP("tgei r%u, %u %u", rs, imm, trap_code);
 
+               if (mode64) {
+                  stmt (IRStmt_Exit (unop (Iop_Not1,
+                                           binop (Iop_CmpLT64S,
+                                                  getIReg (rs),
+                                                  mkU64 (extend_s_16to64 (imm)))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               } else {
+                  stmt (IRStmt_Exit (unop (Iop_Not1,
+                                           binop (Iop_CmpLT32S,
+                                                  getIReg (rs),
+                                                  mkU32 (extend_s_16to32 (imm)))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                }
-               break;
 
-            case 0x0E:  /* CEIL.W.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("ceil.w.s %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, CEILWS, True, 1);
-                     putFReg(fd,
-                          mkWidenFromF32(tyF,
-                                         unop(Iop_ReinterpI32asF32,
-                                              binop(Iop_F32toI32S,
-                                                    mkU32(0x2),
-                                                    getLoFromF64(tyF,
-                                                                 getFReg(fs))))));
-                     break;
-
-                  case 0x11:  /* D */
-                     DIP("ceil.w.d %u, %u", fd, fs);
-                     calculateFCSR(fs, 0, CEILWD, False, 1);
-                     if (!fp_mode64) {
-                        t0 = newTemp(Ity_I32);
-                        assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
-                                         getDReg(fs)));
-                        putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
-                     } 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;
+            case 0x09: {  /* TGEIU */
+               DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
 
+               if (mode64) {
+                  stmt (IRStmt_Exit (unop (Iop_Not1,
+                                           binop (Iop_CmpLT64U,
+                                                  getIReg (rs),
+                                                  mkU64 (extend_s_16to64 (imm)))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               } else {
+                  stmt (IRStmt_Exit (unop (Iop_Not1,
+                                           binop (Iop_CmpLT32U,
+                                                  getIReg (rs),
+                                                  mkU32 (extend_s_16to32 (imm)))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                }
-               break;
 
-            case 0x0A:  /* CEIL.L.fmt */
-               switch (fmt) {
-                  case 0x10:  /* S */
-                     DIP("ceil.l.s %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, CEILLS, True, 1);
-                        t0 = newTemp(Ity_I64);
+               break;
+            }
 
-                        assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
-                                   getLoFromF64(tyF, getFReg(fs))));
+            case 0x0A: {  /* TLTI */
+               DIP("tlti r%u, %u %u", rs, imm, trap_code);
 
-                        putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
+               if (mode64) {
+                  stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
+                                            mkU64 (extend_s_16to64 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               } else {
+                  stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
+                                            mkU32 (extend_s_16to32 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               }
 
-                  case 0x11:  /* D */
-                     DIP("ceil.l.d %u, %u", fd, fs);
-                     if (fp_mode64) {
-                        calculateFCSR(fs, 0, CEILLD, False, 1);
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         binop(Iop_F64toI64S,
-                                               mkU32(0x2),
-                                               getDReg(fs))));
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                     }
-                     break;
+               break;
+            }
 
-                  default:
-                     goto decode_failure;
+            case 0x0B: {  /* TLTIU */
+               DIP("tltiu r%u, %u %u", rs, imm, trap_code);
 
+               if (mode64) {
+                  stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
+                                            mkU64 (extend_s_16to64 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               } else {
+                  stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
+                                            mkU32 (extend_s_16to32 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                }
+
                break;
+            }
 
-            case 0x16:  /* RSQRT.fmt */
-               switch (fmt) {
-                  case 0x10: {  /* S */
-                     DIP("rsqrt.s %u, %u", fd, fs);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
-                                 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
-                                 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
-                                 getFReg(fs))))));
-                     break;
-                  }
-                  case 0x11: {  /* D */
-                     DIP("rsqrt.d %u, %u", fd, fs);
-                     IRExpr *rm = get_IR_roundingmode();
-                     putDReg(fd, triop(Iop_DivF64, rm,
-                                 unop(Iop_ReinterpI64asF64,
-                                 mkU64(ONE_DOUBLE)),
-                                 binop(Iop_SqrtF64, rm, getDReg(fs))));
-                     break;
-                  }
-                  default:
-                     goto decode_failure;
+            case 0x0C: {  /* TEQI */
+               DIP("teqi r%u, %u %u", rs, imm, trap_code);
 
+               if (mode64) {
+                  stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
+                                            mkU64 (extend_s_16to64 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
+               } else {
+                  stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
+                                            mkU32 (extend_s_16to32 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                }
-               break;
 
-            case 0x18: /* MADDF.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
-                        IRExpr *rm = get_IR_roundingmode();
-                        putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
-                                        getDReg(fd)));
-                        break;
-                     }
+               break;
+            }
 
-                     case 0x10: {  /* S */
-                        DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
-                        IRExpr *rm = get_IR_roundingmode();
-                        t1 = newTemp(Ity_F32);
-                        assign(t1, qop(Iop_MAddF32, rm,
-                                       getLoFromF64(tyF, getFReg(fs)),
-                                       getLoFromF64(tyF, getFReg(ft)),
-                                       getLoFromF64(tyF, getFReg(fd))));
-                        putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
-                        break;
-                     }
+            case 0x0E: {  /* TNEI */
+               DIP("tnei r%u, %u %u", rs, imm, trap_code);
 
-                     default:
-                        goto decode_failure;
-                  }
+               if (mode64) {
+                  stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
+                                            mkU64 (extend_s_16to64 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U64(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
+                                            mkU32 (extend_s_16to32 (imm))),
+                                     Ijk_SigTRAP,
+                                     IRConst_U32(guest_PC_curr_instr + 4),
+                                     OFFB_PC));
                }
 
                break;
+            }
 
-            case 0x19: /* MSUBF.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
-                        IRExpr *rm = get_IR_roundingmode();
-                        putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
-                                        getDReg(ft), getDReg(fd)));
-                        break;
-                     }
+            case 0x10:  /* BLTZAL */
+               DIP("bltzal r%u, %u", rs, imm);
 
-                     case 0x10: {  /* S */
-                        DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
-                        IRExpr *rm = get_IR_roundingmode();
-                        t1 = newTemp(Ity_F32);
-                        assign(t1, qop(Iop_MSubF32, rm,
-                                       getLoFromF64(tyF, getFReg(fs)),
-                                       getLoFromF64(tyF, getFReg(ft)),
-                                       getLoFromF64(tyF, getFReg(fd))));
-                        putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
-                        break;
-                     }
+               if (mode64) {
+                  if (!dis_instr_branch(cins, dres, resteerOkFn,
+                                        callback_opaque, bstmt))
+                     return -1;
+               } else
+                  dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                                         mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
 
-                     default:
-                        goto decode_failure;
-                  }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
+               break;
+
+            case 0x11:  /* BGEZAL */
+               DIP("bgezal r%u, %u", rs, imm);
+
+               if (mode64) {
+                  if (!dis_instr_branch(cins, dres, resteerOkFn,
+                                        callback_opaque, bstmt))
+                     return -1;
+               } else
+                  dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                                         mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
 
                break;
 
-            case 0x1E: /* MAX.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("max.d f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MAXD, False, 2);
-                        putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
-                        break;
-                     }
+            case 0x12:  /* BLTZALL */
+               DIP("bltzall r%u, %u", rs, imm);
+               putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
+                       mkU32(guest_PC_curr_instr + 8));
+               *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                                                binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+                                                      mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+                                                mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+                                          imm);
+               break;
 
-                     case 0x10: {  /* S */
-                        DIP("max.s f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MAXS, True, 2);
-                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
-                                                              getLoFromF64(Ity_F64,
-                                                                           getFReg(fs)),
-                                                              getLoFromF64(Ity_F64,
-                                                                           getFReg(ft)))));
-                        break;
-                     }
+            case 0x13:  /* BGEZALL */
+               DIP("bgezall r%u, %u", rs, imm);
 
-                     default:
-                        goto decode_failure;
-                  }
+               if (mode64) {
+                  putIReg(31, mkU64(guest_PC_curr_instr + 8));
+                  *lastn = dis_branch_likely(binop(Iop_CmpNE64,
+                                                   binop(Iop_And64,
+                                                         getIReg(rs),
+                                                         mkU64(0x8000000000000000ULL)),
+                                                   mkU64(0x0)),
+                                             imm);
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  putIReg(31, mkU32(guest_PC_curr_instr + 8));
+                  *lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+                                                   getIReg(rs), mkU32(0x80000000)),
+                                                   mkU32(0x0)), imm);
                }
 
                break;
 
-            case 0x1C: /* MIN.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("min.d f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MIND, False, 2);
-                        putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
-                        break;
-                     }
+            case 0x1C: {  /* BPOSGE32 */
+               DIP("bposge32 %u", imm);
+               vassert(!mode64);
+               t0 = newTemp(Ity_I32);
+               /* Get pos field from DSPControl register. */
+               assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+               dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
+                                                      mkU32(32))), imm, bstmt);
+               break;
+            }
 
-                     case 0x10: {  /* S */
-                        DIP("min.s f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MINS, True, 2);
-                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
-                                                              getLoFromF64(Ity_F64,
-                                                                        getFReg(fs)),
-                                                              getLoFromF64(Ity_F64,
-                                                                     getFReg(ft)))));
-                        break;
-                     }
-                     default:
-                        goto decode_failure;
-                  }
+            case 0x1E: { /* DATI */
+               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                  DIP("dati  r%u,  %x", rs, imm);
+                  putIReg(rs, binop(Iop_Add64,
+                                    getIReg(rs), mkU64((long long)imm << 48)));
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  ILLEGAL_INSTRUCTON
                }
 
                break;
+            }
 
-            case 0x1F: /* MAXA.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MAXAD, False, 2);
-                        t1 = newTemp(Ity_F64);
-                        t2 = newTemp(Ity_F64);
-                        t3 = newTemp(Ity_F64);
-                        t4 = newTemp(Ity_I1);
-                        assign(t1, unop(Iop_AbsF64, getFReg(fs)));
-                        assign(t2, unop(Iop_AbsF64, getFReg(ft)));
-                        assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
-                        assign(t4, binop(Iop_CmpEQ32,
-                                         binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
-                                         mkU32(0x40)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t4),
-                                               getFReg(fs), getFReg(ft)));
-                        break;
-                     }
+            case 0x1F: /* SYNCI */
+               /* Just ignore it */
+               break;
 
-                     case 0x10: {  /* S */
-                        DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MAXAS, True, 2);
-                        t1 = newTemp(Ity_F32);
-                        t2 = newTemp(Ity_F32);
-                        t3 = newTemp(Ity_F32);
-                        t4 = newTemp(Ity_I1);
-                        assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
-                                                                 getFReg(fs))));
-                        assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
-                                                                 getFReg(ft))));
-                        assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
-                        assign(t4, binop(Iop_CmpEQ32,
-                                         binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
-                                         mkU32(0x40)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t4),
-                                               getFReg(fs), getFReg(ft)));
-                        break;
-                     }
+            default:
+               return -1;
+         }
 
-                     default:
-                        goto decode_failure;
-                  }
-                  /* missing in documentation */
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
+         break;
 
-            case 0x1D: /* MINA.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MINAD, False, 2);
-                        t1 = newTemp(Ity_F64);
-                        t2 = newTemp(Ity_F64);
-                        t3 = newTemp(Ity_F64);
-                        t4 = newTemp(Ity_I1);
-                        assign(t1, unop(Iop_AbsF64, getFReg(fs)));
-                        assign(t2, unop(Iop_AbsF64, getFReg(ft)));
-                        assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
-                        assign(t4, binop(Iop_CmpEQ32,
-                                         binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
-                                         mkU32(0x40)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t4),
-                                               getFReg(fs), getFReg(ft)));
-                        break;
-                     }
+      case 0x02:  /* J */
+         DIP("j 0x%x", instr_index);
+         t0 = newTemp(ty);
 
-                     case 0x10: {  /* S */
-                        DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
-                        calculateFCSR(fs, ft, MINAS, True, 2);
-                        t1 = newTemp(Ity_F32);
-                        t2 = newTemp(Ity_F32);
-                        t3 = newTemp(Ity_F32);
-                        t4 = newTemp(Ity_I1);
-                        assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
-                                                                 getFReg(fs))));
-                        assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
-                                                                 getFReg(ft))));
-                        assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
-                        assign(t4, binop(Iop_CmpEQ32,
-                                         binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
-                                         mkU32(0x40)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t4),
-                                               getFReg(fs), getFReg(ft)));
-                        break;
-                     }
+         if (mode64)
+            assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
+                             (instr_index << 2)));
+         else
+            assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+                             (instr_index << 2)));
 
-                     default:
-                        goto decode_failure;
-                  }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
+         *lastn = mkexpr(t0);
+         break;
 
-            case 0x1A: /* RINT.fmt */
-               if (ft == 0) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("rint.d f%u, f%u", fd, fs);
-                        calculateFCSR(fs, 0, RINTS, True, 1);
-                        IRExpr *rm = get_IR_roundingmode();
-                        putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
-                        break;
-                     }
+      case 0x03:  /* JAL */
+         DIP("jal 0x%x", instr_index);
 
-                     case 0x10: {  /* S */
-                        DIP("rint.s f%u, f%u", fd, fs);
-                        calculateFCSR(fs, 0, RINTD, True, 1);
-                        IRExpr *rm = get_IR_roundingmode();
-                        putFReg(fd,
-                                mkWidenFromF32(tyF,
-                                               binop(Iop_RoundF32toInt, rm,
-                                                     getLoFromF64(tyF,
-                                                                  getFReg(fs)))));
-                        break;
-                     }
+         if (mode64) {
+            putIReg(31, mkU64(guest_PC_curr_instr + 8));
+            t0 = newTemp(ty);
+            assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
+                             (instr_index << 2)));
+         } else {
+            putIReg(31, mkU32(guest_PC_curr_instr + 8));
+            t0 = newTemp(ty);
+            assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+                             (instr_index << 2)));
+         }
 
-                     default:
-                        goto decode_failure;
-                  }
+         *lastn = mkexpr(t0);
+         break;
 
-               }
-               break;
+      case 0x04:  /* BEQ */
+         DIP("beq r%u, r%u, %u", rs, rt, imm);
 
-            case 0x10: /* SEL.fmt */
-               switch (fmt) {
-                  case 0x11: {  /* D */
-                     if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                        DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
-                        t1 = newTemp(Ity_I1);
-                        if (mode64) {
-                           assign(t1,binop(Iop_CmpNE64,
-                                          binop(Iop_And64,
-                                                unop(Iop_ReinterpF64asI64,
-                                                     getDReg(fd)),
-                                                mkU64(1)),
-                                          mkU64(0)));
-                        } else {
-                           assign(t1,binop(Iop_CmpNE32,
-                                          binop(Iop_And32,
-                                                unop(Iop_64to32,
-                                                    unop(Iop_ReinterpF64asI64,
-                                                         getDReg(fd))),
-                                                mkU32(1)),
-                                          mkU32(0)));
-                        }
-                        putDReg(fd, IRExpr_ITE(mkexpr(t1),
-                                               getDReg(ft), getDReg(fs)));
-                        break;
-                     } else {
-                        ILLEGAL_INSTRUCTON;
-                        break;
-                     }
+         if (mode64)
+            dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
+                       imm, bstmt);
+         else
+            dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
+                       imm, bstmt);
 
-                  }
+         break;
 
-                  case 0x10: {  /* S */
-                     DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
-                     t1 = newTemp(Ity_I1);
-                     assign(t1,binop(Iop_CmpNE32,
-                                     binop(Iop_And32,
-                                           unop(Iop_ReinterpF32asI32,
-                                                getLoFromF64(tyF, getFReg(fd))),
-                                           mkU32(1)),
-                                     mkU32(0)));
-                     putFReg(fd, IRExpr_ITE( mkexpr(t1),
-                                          getFReg(ft), getFReg(fs)));
-                     break;
-                  }
-                  default:
-                     goto decode_failure;
-               }
-               break;
+      case 0x05:  /* BNE */
+         DIP("bne r%u, r%u, %u", rs, rt, imm);
 
-            case 0x14: /* SELEQZ.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) { /* SELEQZ.df */
-                     case 0x11: {  /* D */
-                        DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
-                        t1 = newTemp(Ity_I1);
-                        if (mode64) {
-                           assign(t1, binop(Iop_CmpNE64,
-                                            binop(Iop_And64,
-                                                  unop(Iop_ReinterpF64asI64,
-                                                       getDReg(ft)),
-                                                  mkU64(1)),
-                                            mkU64(0)));
-                        } else {
-                           assign(t1, binop(Iop_CmpNE32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32,
-                                                       unop(Iop_ReinterpF64asI64,
-                                                            getDReg(ft))),
-                                                  mkU32(1)),
-                                            mkU32(0)));
-                        }
-                        putDReg(fd, IRExpr_ITE( mkexpr(t1),
-                                               binop(Iop_I64StoF64,
-                                                     get_IR_roundingmode(),mkU64(0)),
-                                               getDReg(fs)));
-                        break;
-                     }
+         if (mode64)
+            dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
+                       imm, bstmt);
+         else
+            dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
+                       imm, bstmt);
 
-                     case 0x10: {  /* S */
-                        DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
-                        t1 = newTemp(Ity_I1);
-                        assign(t1, binop(Iop_CmpNE32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(ft))),
-                                               mkU32(1)),
-                                         mkU32(0)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t1),
-                                               mkWidenFromF32(tyF,
-                                                               binop(Iop_I32StoF32,
-                                                                     get_IR_roundingmode(),
-                                                                     mkU32(0))),
-                                               getFReg(fs)));
-                        break;
-                     }
+         break;
 
-                     default:
-                        goto decode_failure;
-                  }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
+      case 0x06:  /* BLEZ, BLEZALC, BGEZALC, BGEUC */
+         if (rt == 0) { /* BLEZ */
+            DIP("blez r%u, %u", rs, imm);
 
-            case 0x17: /* SELNEZ.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
-                        t1 = newTemp(Ity_I1);
-                        if (mode64) {
-                           assign(t1, binop(Iop_CmpNE64,
-                                            binop(Iop_And64,
-                                                  unop(Iop_ReinterpF64asI64,
-                                                       getDReg(ft)),
-                                                  mkU64(1)),
-                                            mkU64(0)));
-                        } else {
-                           assign(t1, binop(Iop_CmpNE32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64to32,
-                                                       unop(Iop_ReinterpF64asI64,
-                                                            getDReg(ft))),
-                                                  mkU32(1)),
-                                            mkU32(0)));
-                        }
-                        putDReg(fd, IRExpr_ITE( mkexpr(t1),
-                                               getDReg(fs),
-                                               binop(Iop_I64StoF64,
-                                                     get_IR_roundingmode(),
-                                                     mkU64(0))));
-                        break;
-                     }
+            if (mode64)
+               dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
+                          imm, bstmt);
+            else
+               dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
+                          bstmt);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) { /* BLEZALC */
+               DIP("blezalc r%u, %u", rt, imm);
 
-                     case 0x10: {  /* S */
-                        DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
-                        t1 = newTemp(Ity_I1);
-                        assign(t1,binop(Iop_CmpNE32,
-                                        binop(Iop_And32,
-                                              unop(Iop_ReinterpF32asI32,
-                                                   getLoFromF64(tyF, getFReg(ft))),
-                                              mkU32(1)),
-                                        mkU32(0)));
-                        putFReg(fd, IRExpr_ITE(mkexpr(t1),
-                                               getFReg(fs),
-                                               mkWidenFromF32(tyF,
-                                                              binop(Iop_I32StoF32,
-                                                                    get_IR_roundingmode(),
-                                                                    mkU32(0)))));
-                        break;
-                     }
+               if (mode64)
+                  dis_branch_compact(True,
+                                     binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
+                                     imm, dres);
+               else
+                  dis_branch_compact(True,
+                                     binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
+                                     imm, dres);
+            } else if (rt == rs) { /* BGEZALC */
+               DIP("bgezalc r%u, %u", rt, imm);
 
-                     default:
-                        goto decode_failure;
-                  }
+               if (mode64)
+                  dis_branch_compact(True,
+                                     binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
+                                     imm, dres);
+               else
+                  dis_branch_compact(True,
+                                     binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
+                                     imm, dres);
+            } else { /* BGEUC */
+               DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
+
+               if (mode64)
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLT64U,
+                                                getIReg(rs), getIReg(rt))),
+                                     imm, dres);
+               else
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLT32U,
+                                                getIReg(rs), getIReg(rt))),
+                                     imm, dres);
+            }
+         } else {
+            ILLEGAL_INSTRUCTON
+         }
+
+         break;
+
+      case 0x07:  /* BGTZ, BGTZALC, BLTZALC, BLTUC */
+         if (rt == 0) { /* BGTZ */
+            DIP("bgtz r%u, %u", rs, imm);
+
+            if (mode64)
+               dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
+                                                      mkU64(0x00))), imm, bstmt);
+            else
+               dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
+                                                      mkU32(0x00))), imm, bstmt);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) { /* BGTZALC */
+               DIP("bgtzalc r%u, %u", rt, imm);
+
+               if (mode64) {
+                  dis_branch_compact(True,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE64S,
+                                                getIReg(rt), mkU64(0x0))),
+                                     imm, dres);
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  dis_branch_compact(True,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE32S,
+                                                getIReg(rt), mkU32(0x0))),
+                                     imm, dres);
                }
-               break;
+            } else if (rs == rt) { /* BLTZALC */
+               DIP("bltzalc r%u, %u", rt, imm);
 
-            case 0x1B: /* CLASS.fmt */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  t0 = newTemp(Ity_I1); // exp zero
-                  t1 = newTemp(Ity_I1); // exp max
-                  t2 = newTemp(Ity_I1); // sign
-                  t3 = newTemp(Ity_I1); // first
-                  t4 = newTemp(Ity_I1); // val not zero
-                  t5 = newTemp(Ity_I32);
-                  switch (fmt) {
-                     case 0x11: {  /* D */
-                        DIP("class.d f%u, f%u", fd, fs);
-                        assign(t0, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_ReinterpF64asI64,
-                                                         getDReg(fs))),
-                                               mkU32(0x7ff00000)),
-                                         mkU32(0)));
-                        assign(t1, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_ReinterpF64asI64,
-                                                         getDReg(fs))),
-                                               mkU32(0x7ff00000)),
-                                         mkU32(0x7ff00000)));
-                        assign(t2, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_ReinterpF64asI64,
-                                                         getDReg(fs))),
-                                               mkU32(0x80000000)),
-                                         mkU32(0x80000000)));
-                        assign(t3, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_64HIto32,
-                                                    unop(Iop_ReinterpF64asI64,
-                                                         getDReg(fs))),
-                                               mkU32(0x00080000)),
-                                         mkU32(0x00080000)));
-                        if (mode64) assign(t4, binop(Iop_CmpNE64,
-                                                    binop(Iop_And64,
-                                                          unop(Iop_ReinterpF64asI64,
-                                                               getDReg(fs)),
-                                                          mkU64(0x000fffffffffffffULL)),
-                                                    mkU64(0)));
-                        else assign(t4, binop(Iop_CmpNE32,
-                                              binop(Iop_Or32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               unop(Iop_ReinterpF64asI64,
-                                                                    getDReg(fs))),
-                                                          mkU32(0x000fffff)),
-                                                    unop(Iop_64to32,
-                                                         unop(Iop_ReinterpF64asI64,
-                                                            getDReg(fs)))),
-                                              mkU32(0)));
-                        assign(t5, binop(Iop_Shl32,
-                                         IRExpr_ITE(mkexpr(t1),
-                                                    IRExpr_ITE(mkexpr(t4),
-                                                               mkU32(0), mkU32(1)),
-                                                    IRExpr_ITE(mkexpr(t0),
-                                                               IRExpr_ITE(mkexpr(t4),
-                                                                          mkU32(0x4),
-                                                                          mkU32(0x8)),
-                                                               mkU32(2))),
-                                         IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         unop(Iop_32Uto64,
-                                              IRExpr_ITE(binop(Iop_CmpNE32,
-                                                               mkexpr(t5), mkU32(0)),
-                                                         mkexpr(t5),
-                                                         IRExpr_ITE(mkexpr(t3),
-                                                                    mkU32(2),
-                                                                    mkU32(1))))));
-                        break;
-                     }
-                     case 0x10: {  /* S */
-                        DIP("class.s f%u, f%u", fd, fs);
-                        assign(t0, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(fs))),
-                                               mkU32(0x7f800000)),
-                                         mkU32(0)));
-                        assign(t1, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(fs))),
-                                               mkU32(0x7f800000)),
-                                         mkU32(0x7f800000)));
-                        assign(t2, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(fs))),
-                                               mkU32(0x80000000)),
-                                         mkU32(0x80000000)));
-                        assign(t3, binop(Iop_CmpEQ32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(fs))),
-                                               mkU32(0x00400000)),
-                                         mkU32(0x00400000)));
-                        assign(t4, binop(Iop_CmpNE32,
-                                         binop(Iop_And32,
-                                               unop(Iop_ReinterpF32asI32,
-                                                    getLoFromF64(tyF, getFReg(fs))),
-                                               mkU32(0x007fffff)),
-                                         mkU32(0)));
-                        assign(t5, binop(Iop_Shl32,
-                                         IRExpr_ITE(mkexpr(t1),
-                                                    IRExpr_ITE(mkexpr(t4),
-                                                               mkU32(0), mkU32(1)),
-                                                    IRExpr_ITE(mkexpr(t0),
-                                                               IRExpr_ITE(mkexpr(t4),
-                                                                          mkU32(0x4),
-                                                                          mkU32(0x8)), //zero or subnorm
-                                                               mkU32(2))),
-                                         IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
-                        putDReg(fd, unop(Iop_ReinterpI64asF64,
-                                         unop(Iop_32Uto64,
-                                              IRExpr_ITE(binop(Iop_CmpNE32,
-                                                               mkexpr(t5), mkU32(0)),
-                                                         mkexpr(t5),
-                                                         IRExpr_ITE(mkexpr(t3),
-                                                                    mkU32(2),
-                                                                    mkU32(1))))));
-                        break;
-                     }
-                     default:
-                        goto decode_failure;
-                  }
+               if (mode64) {
+                  dis_branch_compact(True,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE64S,
+                                                mkU64(0x0), getIReg(rt))),
+                                     imm, dres);
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  dis_branch_compact(True,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE32S,
+                                                mkU32(0x0), getIReg(rt))),
+                                     imm, dres);
                }
-               break;
+            } else { /* BLTUC */
+               DIP("bltuc r%u, r%u, %u", rt, rs, imm);
+
+               if (mode64) {
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
+                                     imm, dres);
+               } else {
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
+                                     imm, dres);
+               }
+            }
+         } else {
+            ILLEGAL_INSTRUCTON
+         }
+
+         break;
+
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
+
+      case 0x08: {  /* ADDI */
+         DIP("addi r%u, r%u, %u", rt, rs, imm);
+         IRTemp tmpRs32, t1, t2, t3, t4;
+         tmpRs32 = newTemp(Ity_I32);
+         assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         /* dst = src0 + sign(imm)
+         if(sign(src0 ) != sign(imm ))
+         goto no overflow;
+         if(sign(dst) == sign(src0 ))
+         goto no overflow;
+         we have overflow! */
+
+         assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
+                          mkU32(extend_s_16to32(imm))));
+         assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
+                          mkU32(extend_s_16to32(imm))));
+         assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
+                                           mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+
+         assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+         assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
+                                           mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
+                                mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
+                          mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+                          IRConst_U32(guest_PC_curr_instr + 4),
+                          OFFB_PC));
+
+         putIReg(rt,  mkWidenFrom32(ty, mkexpr(t0), True));
+         break;
+      }
 
-            default:
-               if (dis_instr_CCondFmt(cins))
-                  break;
-               goto decode_failure;
+#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
+
+      case 0x08: { /* BEQZALC, BEQC, BOVC */
+         if (rs == 0) { /* BEQZALC */
+            DIP("beqzalc r%u, %u", rt, imm);
+
+            if (mode64) {
+               dis_branch_compact(True,
+                                  binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
+                                  imm, dres);
+            } else {
+               dis_branch_compact(True,
+                                  binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
+                                  imm, dres);
+            }
+         } else  if (rs < rt) { /* BEQC */
+            DIP("beqc r%u, r%u, %u", rs, rt, imm);
 
+            if (mode64) {
+               dis_branch_compact(False,
+                                  binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
+                                  imm, dres);
+            } else {
+               dis_branch_compact(False,
+                                  binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
+                                  imm, dres);
             }
+         } else { /* BOVC */
+            DIP("bovc r%u, r%u, %u", rs, rt, imm);
+
+            if (mode64) {
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           getIReg(rt),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      getIReg(rt),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           getIReg(rs),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      getIReg(rs),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           binop(Iop_Add64,
+                                                 getIReg(rt), getIReg(rs)),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      binop(Iop_Add64,
+                                                            getIReg(rt),
+                                                            getIReg(rs)),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t3, binop(Iop_Add32,
+                                mkexpr(t0),
+                                binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
+               dis_branch_compact(False,
+                                  binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
+                                  imm, dres);
+            } else {
+               IRTemp tmpRs32 = newTemp(Ity_I32);
+               IRTemp tmpRt32 = newTemp(Ity_I32);
+               assign(tmpRs32, getIReg(rs));
+               assign(tmpRt32, getIReg(rt));
+
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               t4 = newTemp(Ity_I32);
+               /* dst = src0 + src1
+               if (sign(src0 ) != sign(src1 ))
+               goto no overflow;
+               if (sign(dst) == sign(src0 ))
+               goto no overflow;
+               we have overflow! */
 
+               assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+               assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+               assign(t2, unop(Iop_1Uto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+                                     mkU32(0x80000000))));
+
+               assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+               assign(t4, unop(Iop_1Uto32,
+                               binop(Iop_CmpNE32,
+                                     binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+                                     mkU32(0x80000000))));
+
+               dis_branch_compact(False, binop(Iop_CmpEQ32,
+                                               binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+                                               mkU32(0)), imm, dres);
+            }
          }
+
+         break;
+         /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
       }
-      break;  /* COP1 */
 
-   case 0x31:  /* LWC1 */
-      /* Load Word to Floating Point - LWC1 (MIPS32) */
-      DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (fp_mode64) {
-         t0 = newTemp(Ity_F32);
-         t2 = newTemp(Ity_I64);
-         assign(t0, load(Ity_F32, mkexpr(t1)));
-         assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
-                                                mkexpr(t0)), True));
-         putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
-      } else {
-         putFReg(ft, load(Ity_F32, mkexpr(t1)));
-      }
-      break;
-
-   case 0x39:  /* SWC1 */
-      DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
-      if (fp_mode64) {
-         t0 = newTemp(Ity_I64);
-         t2 = newTemp(Ity_I32);
-         LOAD_STORE_PATTERN;
-         assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
-         assign(t2, unop(Iop_64to32, mkexpr(t0)));
-         store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
-      } else {
-         LOAD_STORE_PATTERN;
-         store(mkexpr(t1), getFReg(ft));
-      }
-      break;
-
-   case 0x33:  /* PREF */
-      DIP("pref");
-      break;
-
-   case 0x35:
-      /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
-      DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      putDReg(ft, load(Ity_F64, mkexpr(t1)));
-      break;
-
-   case 0x3D:
-      /* Store Doubleword from Floating Point - SDC1 */
-      DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
-      LOAD_STORE_PATTERN;
-      store(mkexpr(t1), getDReg(ft));
-      break;
-
-   case 0x23:  /* LW */
-      DIP("lw r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
-      break;
-
-   case 0x20:  /* LB */
-      DIP("lb r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
-      else
-         putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
-      break;
+#endif
 
-   case 0x24:  /* LBU */
-      DIP("lbu r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
-      else
-         putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
-      break;
+      case 0x09:  /* ADDIU */
+         DIP("addiu r%u, r%u, %u", rt, rs, imm);
 
-   case 0x21:  /* LH */
-      DIP("lh r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
-      else
-         putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
-      break;
+         if (mode64) {
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
+                                                mkNarrowTo32(ty, getIReg(rs)), mkU32(extend_s_16to32(imm))),
+                                      True));
+         } else
+            putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
 
-   case 0x25:  /* LHU */
-      DIP("lhu r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (mode64)
-         putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
-      else
-         putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
-      break;
+         break;
+
+      case 0x0A:  /* SLTI */
+         DIP("slti r%u, r%u, %u", rt, rs, imm);
 
-   case 0x0F:  /* LUI */
-      if (rs == 0) {
-         p = (imm << 16);
-         DIP("lui r%u, imm: 0x%x", rt, imm);
          if (mode64)
-            putIReg(rt, mkU64(extend_s_32to64(p)));
+            putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
+                                               mkU64(extend_s_16to64(imm)))));
          else
-            putIReg(rt, mkU32(p));
+            putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+                                               mkU32(extend_s_16to32(imm)))));
+
          break;
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
-         DIP("aui r%u, imm: 0x%x", rt, imm);
-         if (mode64) {
-            putIReg(rt, unop(Iop_32Sto64,
-                             unop(Iop_64to32,
-                                  binop(Iop_Add64,
-                                        getIReg(rs),
-                                        mkU64(extend_s_32to64(imm << 16))))));
-         } else {
-            putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
 
-   case 0x13:  /* COP1X */
-      switch (function) {
-      case 0x0: {  /* LWXC1 */
-         /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
-         DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
-         t2 = newTemp(ty);
-         assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                          getIReg(rt)));
-         if (fp_mode64) {
-            t0 = newTemp(Ity_I64);
-            t1 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_F32);
-            t4 = newTemp(Ity_I64);
-            assign(t3, load(Ity_F32, mkexpr(t2)));
+      case 0x0B:  /* SLTIU */
+         DIP("sltiu r%u, r%u, %u", rt, rs, imm);
 
-            assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
-                                                   mkexpr(t3)), True));
+         if (mode64)
+            putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
+                                               mkU64(extend_s_16to64(imm)))));
+         else
+            putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+                                               mkU32(extend_s_16to32(imm)))));
 
-            putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
-         } else {
-            putFReg(fd, load(Ity_F32, mkexpr(t2)));
-         }
          break;
-      }
 
-      case 0x1: {  /* LDXC1 */
-         /* Load Doubleword  Indexed to Floating Point
-            LDXC1 (MIPS32r2 and MIPS64) */
-         DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
-         t0 = newTemp(ty);
-         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                          getIReg(rt)));
-         putDReg(fd, load(Ity_F64, mkexpr(t0)));
-         break;
-      }
+      case 0x0C:  /* ANDI */
+         DIP("andi r%u, r%u, %u", rt, rs, imm);
 
-      case 0x5:  /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
-                    MIPS32r2 and MIPS64 */
-         DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
-         if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
-             && fp_mode64) {
-            t0 = newTemp(ty);
-            t1 = newTemp(ty);
-            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
-                             getIReg(rs), getIReg(rt)));
-            assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
-                             mkexpr(t0),
-                             mode64 ? mkU64(0xfffffffffffffff8ULL)
-                                    : mkU32(0xfffffff8ULL)));
-            putFReg(fd, load(Ity_F64, mkexpr(t1)));
+         if (mode64) {
+            ALUI_PATTERN64(Iop_And64);
          } else {
-            ILLEGAL_INSTRUCTON;
+            ALUI_PATTERN(Iop_And32);
          }
-         break;
 
-      case 0x8: {  /* Store Word Indexed from Floating Point - SWXC1 */
-         DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
-         t0 = newTemp(ty);
-         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                          getIReg(rt)));
-         if (fp_mode64) {
-            store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
-         } else {
-            store(mkexpr(t0), getFReg(fs));
-         }
-         break;
-      }
-      case 0x9: {  /* Store Doubleword Indexed from Floating Point - SDXC1 */
-         DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
-         t0 = newTemp(ty);
-         assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
-                          getIReg(rt)));
-         store(mkexpr(t0), getDReg(fs));
-         break;
-      }
-      case 0xD:  /* Store Doubleword Indexed Unaligned from Floating Point -
-                    SUXC1; MIPS64 MIPS32r2 */
-         DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
-         if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
-             && fp_mode64) {
-            t0 = newTemp(ty);
-            t1 = newTemp(ty);
-            assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
-                             getIReg(rs), getIReg(rt)));
-            assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
-                             mkexpr(t0),
-                             mode64 ? mkU64(0xfffffffffffffff8ULL)
-                                    : mkU32(0xfffffff8ULL)));
-            store(mkexpr(t1), getFReg(fs));
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
          break;
 
-      case 0x0F: {
-         DIP("prefx");
-         break;
-      }
-      case 0x20:  {  /* MADD.S */
-         DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F32);
-         assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
-            triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
-               getLoFromF64(tyF, getFReg(ft)))));
-         putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
-         break;  /* MADD.S */
-      }
-      case 0x21: {  /* MADD.D */
-         DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
-            triop(Iop_MulF64, rm, getDReg(fs),
-                         getDReg(ft))));
-         break;  /* MADD.D */
-      }
-      case 0x28: {  /* MSUB.S */
-         DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F32);
-         assign(t1, triop(Iop_SubF32, rm,
-            triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
-               getLoFromF64(tyF, getFReg(ft))),
-             getLoFromF64(tyF, getFReg(fmt))));
-         putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
-         break;  /* MSUB.S */
-      }
-      case 0x29: {  /* MSUB.D */
-         DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
-                         getDReg(ft)), getDReg(fmt)));
-         break;  /* MSUB.D */
-      }
-      case 0x30: {  /* NMADD.S */
-         DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F32);
-         assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
-            triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
-               getLoFromF64(tyF, getFReg(ft)))));
-         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
-         break;  /* NMADD.S */
-      }
-      case 0x31: {  /* NMADD.D */
-         DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F64);
-         assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
-            triop(Iop_MulF64, rm, getDReg(fs),
-                         getDReg(ft))));
-         putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
-         break;  /* NMADD.D */
-      }
-      case 0x38: {  /* NMSUBB.S */
-         DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F32);
-         assign(t1, triop(Iop_SubF32, rm,
-            triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
-               getLoFromF64(tyF, getFReg(ft))),
-             getLoFromF64(tyF, getFReg(fmt))));
-         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
-         break;  /* NMSUBB.S */
-      }
-      case 0x39: {  /* NMSUBB.D */
-         DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
-         IRExpr *rm = get_IR_roundingmode();
-         t1 = newTemp(Ity_F64);
-         assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
-                         getDReg(ft)), getDReg(fmt)));
-         putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
-         break;  /* NMSUBB.D */
-      }
-
-      default:
-         goto decode_failure;
-      }
-      break;
-
-   case 0x22:  /* LWL */
-      DIP("lwl r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         /* t1 = addr */
-         t1 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
-         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
-         assign(t1, binop(Iop_Xor64,
-                          mkU64(0x03),
-                          binop(Iop_Add64,
-                                getIReg(rs),
-                                mkU64(extend_s_16to64(imm)))));
-#endif
-         /* t2 = word addr */
-         /* t4 = addr mod 4 */
-         LWX_SWX_PATTERN64;
-
-         /* t3 = word content - shifted */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shl32,
-                          load(Ity_I32, mkexpr(t2)),
-                          narrowTo(Ity_I8,
-                                   binop(Iop_Shl32,
-                                         binop(Iop_Sub32,
-                                               mkU32(0x03),
-                                               mkexpr(t4)),
-                                         mkU8(3)))));
-
-         /* rt content - adjusted */
-         t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32,
-                          mkNarrowTo32(ty, getIReg(rt)),
-                          binop(Iop_Shr32,
-                                mkU32(0x00FFFFFF),
-                                      narrowTo(Ity_I8, binop(Iop_Mul32,
-                                                             mkU32(0x08),
-                                                             mkexpr(t4))))));
-
-         putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
-                                             mkexpr(t3)), True));
-      } else {
-         /* t1 = addr */
-         t1 = newTemp(Ity_I32);
-#if defined (_MIPSEL)
-         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
-#elif defined (_MIPSEB)
-         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
-                                     mkU32(extend_s_16to32(imm)))));
-#endif
+      case 0x0D:  /* ORI */
+         DIP("ori r%u, r%u, %u", rt, rs, imm);
 
-         /* t2 = word addr */
-         /* t4 = addr mod 4 */
-         LWX_SWX_PATTERN;
+         if (mode64) {
+            ALUI_PATTERN64(Iop_Or64);
+         } else {
+            ALUI_PATTERN(Iop_Or32);
+         }
 
-         /* t3 = word content - shifted */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
-                    binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
-                    mkU8(3)))));
+         break;
 
-         /* rt content  - adjusted */
-         t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32,
-                          getIReg(rt),
-                          binop(Iop_Shr32,
-                                mkU32(0x00FFFFFF),
-                                      narrowTo(Ity_I8, binop(Iop_Mul32,
-                                                             mkU32(0x08),
-                                                             mkexpr(t4))))));
+      case 0x0E:  /* XORI */
+         DIP("xori r%u, r%u, %u", rt, rs, imm);
 
-         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
-      }
-      break;
+         if (mode64) {
+            ALUI_PATTERN64(Iop_Xor64);
+         } else {
+            ALUI_PATTERN(Iop_Xor32);
+         }
 
-   case 0x26:  /* LWR */
-      DIP("lwr r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         /* t1 = addr */
-         t1 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
-         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
-         assign(t1, binop(Iop_Xor64,
-                          mkU64(0x3),
-                          binop(Iop_Add64,
-                                getIReg(rs),
-                                mkU64(extend_s_16to64(imm)))));
-#endif
-         /* t2 = word addr */
-         /* t4 = addr mod 4 */
-         LWX_SWX_PATTERN64;
+         break;
 
-         /* t3 = word content - shifted */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shr32,
-                          load(Ity_I32, mkexpr(t2)),
-                          narrowTo(Ity_I8,
-                                   binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
+      case 0x0F:  /* LUI */
+         if (rs == 0) {
+            p = (imm << 16);
+            DIP("lui r%u, imm: 0x%x", rt, imm);
 
-         /* rt content  - adjusted */
-         t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
-                unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
-                narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+            if (mode64)
+               putIReg(rt, mkU64(extend_s_32to64(p)));
+            else
+               putIReg(rt, mkU32(p));
 
-         putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
-                                       mkexpr(t3)), True));
+            break;
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
+            DIP("aui r%u, imm: 0x%x", rt, imm);
 
-      } else {
-         /* t1 = addr */
-         t1 = newTemp(Ity_I32);
-#if defined (_MIPSEL)
-         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
-#elif defined (_MIPSEB)
-         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
-                                     mkU32(extend_s_16to32(imm)))));
-#endif
+            if (mode64) {
+               putIReg(rt, unop(Iop_32Sto64,
+                                unop(Iop_64to32,
+                                     binop(Iop_Add64,
+                                           getIReg(rs),
+                                           mkU64(extend_s_32to64(imm << 16))))));
+            } else {
+               putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
+            }
 
-         /* t2 = word addr */
-         /* t4 = addr mod 4 */
-         LWX_SWX_PATTERN;
+         } else {
+            ILLEGAL_INSTRUCTON
+         }
 
-         /* t3 = word content - shifted */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
-                    narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
-                    mkU8(3)))));
+         break;
 
-         /* rt content  - adjusted */
-         t5 = newTemp(Ity_I32);
-         assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
-                    binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
-                          binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+      default:
+         return -1;
+   }
 
-         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
-      }
-      break;
+   return 0;
+}
 
-   case 0x2B:  /* SW */
-      DIP("sw r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
-      break;
+static UInt disInstr_MIPS_WRK_10(UInt cins, const VexArchInfo* archinfo,
+                                 const VexAbiInfo*  abiinfo, DisResult* dres,
+                                 IRStmt** bstmt, IRExpr** lastn,
+                                 Bool(*resteerOkFn) (/*opaque */void *,
+                                       Addr),
+                                 void*        callback_opaque)
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
+   UInt opcode, rs, rt, ft, fs, fd, fmt, tf, nd, function, imm;
+   /* Additional variables for instruction fields in DSP ASE insructions */
 
-   case 0x2C: {  /* SDL rt, offset(base) MIPS64 */
-      DIP("sdl r%u, %u(r%u)", rt, imm, rs);
-      vassert(mode64);
-      IRTemp A_byte = newTemp(Ity_I8);
-      IRTemp B_byte = newTemp(Ity_I8);
-      IRTemp C_byte = newTemp(Ity_I8);
-      IRTemp D_byte = newTemp(Ity_I8);
-      IRTemp E_byte = newTemp(Ity_I8);
-      IRTemp F_byte = newTemp(Ity_I8);
-      IRTemp G_byte = newTemp(Ity_I8);
-      IRTemp H_byte = newTemp(Ity_I8);
-      IRTemp B_pos  = newTemp(Ity_I64);
-      IRTemp C_pos  = newTemp(Ity_I64);
-      IRTemp D_pos  = newTemp(Ity_I64);
-      IRTemp E_pos  = newTemp(Ity_I64);
-      IRTemp F_pos  = newTemp(Ity_I64);
-      IRTemp G_pos  = newTemp(Ity_I64);
-
-      /* H byte */
-      assign(H_byte, getByteFromReg(rt, 0));
-      /* G byte */
-      assign(G_byte, getByteFromReg(rt, 1));
-      /* F byte */
-      assign(F_byte, getByteFromReg(rt, 2));
-      /* E byte */
-      assign(E_byte, getByteFromReg(rt, 3));
-      /* D byte */
-      assign(D_byte, getByteFromReg(rt, 4));
-      /* C byte */
-      assign(C_byte, getByteFromReg(rt, 5));
-      /* B byte */
-      assign(B_byte, getByteFromReg(rt, 6));
-      /* A byte */
-      assign(A_byte, getByteFromReg(rt, 7));
-
-      /* t1 = addr */
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-
-      /* t2 = word addr */
-      t2 = newTemp(Ity_I64);
-      assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
-
-      /* t3 = addr mod 7 */
-      t3 = newTemp(Ity_I64);
-      assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+   opcode = get_opcode(cins);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   fs = get_fs(cins);
+   fd = get_fd(cins);
+   ft = get_ft(cins);
+   tf = get_tf(cins);
+   nd = get_nd(cins);
+   fmt = get_fmt(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
 
-#if defined (_MIPSEL)
-      /* Calculate X_byte position. */
-      assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
-                               mkU64(0x0),
-                               mkU64(0x1)));
-
-      assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
-                               mkU64(0x0),
-                               mkU64(0x2)));
-
-      assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
-                               mkU64(0x0),
-                               mkU64(0x3)));
-
-      assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
-                               mkU64(0x0),
-                               mkU64(0x4)));
-
-      assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
-                               mkU64(0x0),
-                               mkU64(0x5)));
-
-      assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
-                               mkU64(0x1),
-                               mkU64(0x0)));
-
-      /* Store X_byte on the right place. */
-      store(mkexpr(t2), mkexpr(H_byte));
-      store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
-      store(mkexpr(t1), mkexpr(A_byte));
+   switch (opcode & 0x0F) {
+      case 0x01: {  /* COP1 */
+         if (fmt == 0x3 && fd == 0 && function == 0) {  /* MFHC1 */
+            DIP("mfhc1 r%u, f%u", rt, fs);
 
-#else /* _MIPSEB */
-      /* Calculate X_byte position. */
-      assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
-                               mkU64(0x0),
-                               mkU64(0x1)));
-
-      assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
-                               mkU64(0x2),
-                               mkU64(0x0)));
-
-      assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
-                               mkU64(0x3),
-                               mkU64(0x0)));
-
-      assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
-                               mkU64(0x4),
-                               mkU64(0x0)));
-
-      assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
-                               mkU64(0x5),
-                               mkU64(0x0)));
-
-      assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                               mkU64(0x6),
-                               mkU64(0x7)));
-
-      /* Store X_byte on the right place. */
-      store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
-      store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
-      store(mkexpr(t1), mkexpr(A_byte));
-#endif
+            if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+                  VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               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 {
+                  putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
+                                                     getFReg(fs | 1)), True));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
 
-      break;
-   }
+            break;
+         } else if (fmt == 0x7 && fd == 0 && function == 0) {  /* MTHC1 */
+            DIP("mthc1 r%u, f%u", rt, fs);
 
-   case 0x2D: {
-      /* SDR rt, offset(base) - MIPS64 */
-      vassert(mode64);
-      DIP("sdr r%u, %u(r%u)", rt, imm, rs);
-      IRTemp A_byte = newTemp(Ity_I8);
-      IRTemp B_byte = newTemp(Ity_I8);
-      IRTemp C_byte = newTemp(Ity_I8);
-      IRTemp D_byte = newTemp(Ity_I8);
-      IRTemp E_byte = newTemp(Ity_I8);
-      IRTemp F_byte = newTemp(Ity_I8);
-      IRTemp G_byte = newTemp(Ity_I8);
-      IRTemp H_byte = newTemp(Ity_I8);
-      IRTemp B_pos  = newTemp(Ity_I64);
-      IRTemp C_pos  = newTemp(Ity_I64);
-      IRTemp D_pos  = newTemp(Ity_I64);
-      IRTemp E_pos  = newTemp(Ity_I64);
-      IRTemp F_pos  = newTemp(Ity_I64);
-      IRTemp G_pos  = newTemp(Ity_I64);
-
-      /* H byte */
-      assign(H_byte, getByteFromReg(rt, 0));
-      /* G byte */
-      assign(G_byte, getByteFromReg(rt, 1));
-      /* F byte */
-      assign(F_byte, getByteFromReg(rt, 2));
-      /* E byte */
-      assign(E_byte, getByteFromReg(rt, 3));
-      /* D byte */
-      assign(D_byte, getByteFromReg(rt, 4));
-      /* C byte */
-      assign(C_byte, getByteFromReg(rt, 5));
-      /* B byte */
-      assign(B_byte, getByteFromReg(rt, 6));
-      /* A byte */
-      assign(A_byte, getByteFromReg(rt, 7));
-
-      /* t1 = addr */
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-
-      /* t2 = word addr */
-      t2 = newTemp(Ity_I64);
-      assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
-
-      /* t3 = addr mod 7 */
-      t3 = newTemp(Ity_I64);
-      assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+            if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+                  VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               if (fp_mode64) {
+                  t0 = newTemp(Ity_I64);
+                  assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
+                                   unop(Iop_ReinterpF32asI32,
+                                        getLoFromF64(Ity_F64, getDReg(fs)))));
+                  putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+               } else {
+                  putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
+                                       mkNarrowTo32(ty, getIReg(rt))));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
 
-#if defined (_MIPSEL)
-      /* Calculate X_byte position. */
-      assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
-                               mkU64(0x0),
-                               mkU64(0x6)));
-
-      assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
-                               mkU64(0x0),
-                               mkU64(0x5)));
-
-      assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
-                               mkU64(0x0),
-                               mkU64(0x4)));
-
-      assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
-                               mkU64(0x0),
-                               mkU64(0x3)));
-
-      assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
-                               mkU64(0x0),
-                               mkU64(0x2)));
-
-      assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
-                               mkU64(0x0),
-                               mkU64(0x1)));
-
-      /* Store X_byte on the right place. */
-      store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-      store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-      store(mkexpr(t1), mkexpr(H_byte));
+            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);
 
-#else /* _MIPSEB */
-      /* Calculate X_byte position. */
-      assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
-                               mkU64(0x6),
-                               mkU64(0x0)));
-
-      assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
-                               mkU64(0x5),
-                               mkU64(0x0)));
-
-      assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
-                               mkU64(0x4),
-                               mkU64(0x0)));
-
-      assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
-                               mkU64(0x3),
-                               mkU64(0x0)));
-
-      assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
-                               mkU64(0x2),
-                               mkU64(0x0)));
-
-      assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                               mkU64(0x0),
-                               mkU64(0x1)));
-
-      /* Store X_byte on the right place. */
-      store(mkexpr(t2), mkexpr(A_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-      store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-      store(mkexpr(t1), mkexpr(H_byte));
-#endif
-      break;
-   }
+            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 %u, %u", 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 %u, %u", 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 %u, %u", bc1_cc, imm);
+               *lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
+                                                mkU32(0x0)), imm);
+               break;
+            } else if (nd == 1 && tf == 1) {
+               DIP("bc1tl %u, %u", bc1_cc, imm);
+               *lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
+                                                mkU32(0x0)), imm);
+               break;
+            } else
+               return -1;
+         } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
+            Int df = fmt & 3;
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_V128);
+            t2 = newTemp(Ity_V128);
+            t3 = newTemp(Ity_V128);
+            assign(t1, getWReg(ft));
+            assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
 
-   case 0x28:  /* SB */
-      DIP("sb r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
-      break;
-
-   case 0x29:  /* SH */
-      DIP("sh r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
-      break;
-
-   case 0x2A:  /* SWL */
-      DIP("swl r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         IRTemp E_byte = newTemp(Ity_I8);
-         IRTemp F_byte = newTemp(Ity_I8);
-         IRTemp G_byte = newTemp(Ity_I8);
-         IRTemp H_byte = newTemp(Ity_I8);
-         IRTemp F_pos  = newTemp(Ity_I64);
-         IRTemp G_pos  = newTemp(Ity_I64);
+            switch (df) {
+               case 0x00: { /* BNZ.B */
+                  DIP("BNZ.B w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-         /* H byte */
-         assign(H_byte, getByteFromReg(rt, 0));
-         /* G byte */
-         assign(G_byte, getByteFromReg(rt, 1));
-         /* F byte */
-         assign(F_byte, getByteFromReg(rt, 2));
-         /* E byte */
-         assign(E_byte, getByteFromReg(rt, 3));
+               case 0x01: { /* BNZ.H */
+                  DIP("BNZ.H w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-         /* t1 = addr */
-         t1 = newTemp(Ity_I64);
-         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+               case 0x02: { /* BNZ.W */
+                  DIP("BNZ.W w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-         /* t2 = word addr */
-         t2 = newTemp(Ity_I64);
-         assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+               case 0x03: { /* BNZ.D */
+                  DIP("BNZ.D w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
+            }
 
-         /* t3 = addr mod 4 */
-         t3 = newTemp(Ity_I64);
-         assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+            assign(t0,
+                   binop(Iop_Or32,
+                         binop(Iop_Or32,
+                               unop(Iop_V128to32, mkexpr(t3)),
+                               unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
+                         binop(Iop_Or32,
+                               unop(Iop_64to32,
+                                    unop(Iop_V128HIto64, mkexpr(t3))),
+                               unop(Iop_64HIto32,
+                                    unop(Iop_V128HIto64, mkexpr(t3))))));
+            dis_branch(False,
+                       binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
+         } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_V128);
+            assign(t1, getWReg(ft));
+            assign(t0,
+                   binop(Iop_Or32,
+                         binop(Iop_Or32,
+                               unop(Iop_V128to32, mkexpr(t1)),
+                               unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
+                         binop(Iop_Or32,
+                               unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
+                               unop(Iop_64HIto32,
+                                    unop(Iop_V128HIto64, mkexpr(t1))))));
+            dis_branch(False,
+                       binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
+         } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
+            Int df = fmt & 3;
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_V128);
+            t2 = newTemp(Ity_V128);
+            t3 = newTemp(Ity_V128);
+            assign(t1, getWReg(ft));
+            assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
 
-#if defined (_MIPSEL)
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                                  mkU64(0x0),
-                                  mkU64(0x1)));
+            switch (df) {
+               case 0x00: { /* BZ.B */
+                  DIP("BZ.B w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
-                                  mkU64(0x1),
-                                  mkU64(0x0)));
+               case 0x01: { /* BZ.H */
+                  DIP("BZ.H w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-         /* Store X_byte on the right place. */
-         store(mkexpr(t2), mkexpr(H_byte));
-         store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-         store(mkexpr(t1), mkexpr(E_byte));
+               case 0x02: { /* BZ.W */
+                  DIP("BZ.W w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
 
-#else    /* _MIPSEB */
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
-                                  mkU64(0x0),
-                                  mkU64(0x1)));
+               case 0x03: { /* BZ.D */
+                  DIP("BZ.D w%u, %u", ft, imm);
+                  assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+                  break;
+               }
+            }
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                                  mkU64(0x2),
-                                  mkU64(0x3)));
+            assign(t0,
+                   binop(Iop_Or32,
+                         binop(Iop_Or32,
+                               unop(Iop_V128to32, mkexpr(t3)),
+                               unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
+                         binop(Iop_Or32,
+                               unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
+                               unop(Iop_64HIto32,
+                                    unop(Iop_V128HIto64, mkexpr(t3))))));
+            dis_branch(False,
+                       binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
+         } else if (fmt == 0x0B && has_msa) { /* BZ.V */
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_V128);
+            assign(t1, getWReg(ft));
+            assign(t0,
+                   binop(Iop_Or32,
+                         binop(Iop_Or32,
+                               unop(Iop_V128to32, mkexpr(t1)),
+                               unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
+                         binop(Iop_Or32,
+                               unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
+                               unop(Iop_64HIto32,
+                                    unop(Iop_V128HIto64, mkexpr(t1))))));
+            dis_branch(False,
+                       binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
+         } else if (fmt == 0x09) { /* BC1EQZ */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("bc1eqz f%u, %u", ft, imm);
+               t1 = newTemp(Ity_I1);
 
-         store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
-         store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-         store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-         store(mkexpr(t1), mkexpr(E_byte));
+               if (mode64) {
+                  assign(t1, binop(Iop_CmpEQ64,
+                                   binop(Iop_And64,
+                                         unop(Iop_ReinterpF64asI64, getDReg(ft)),
+                                         mkU64(1)),
+                                   mkU64(0)));
+               } else {
+                  assign(t1, binop(Iop_CmpEQ32,
+                                   binop(Iop_And32,
+                                         unop(Iop_64to32,
+                                              unop(Iop_ReinterpF64asI64,
+                                                   getDReg(ft))),
+                                         mkU32(1)),
+                                   mkU32(0)));
+               }
 
-#endif
-      } else {
-         IRTemp E_byte = newTemp(Ity_I8);
-         IRTemp F_byte = newTemp(Ity_I8);
-         IRTemp G_byte = newTemp(Ity_I8);
-         IRTemp H_byte = newTemp(Ity_I8);
-         IRTemp F_pos  = newTemp(Ity_I32);
-         IRTemp G_pos  = newTemp(Ity_I32);
+               dis_branch(False, mkexpr(t1), imm, bstmt);
+            } else {
+               ILLEGAL_INSTRUCTON
+            }
+         } else if (fmt == 0x0D) { /* BC1NEZ */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("bc1nez f%u, %u", ft, imm);
+               t1 = newTemp(Ity_I1);
 
-         /* H byte */
-         assign(H_byte, getByteFromReg(rt, 0));
-         /* G byte */
-         assign(G_byte, getByteFromReg(rt, 1));
-         /* F byte */
-         assign(F_byte, getByteFromReg(rt, 2));
-         /* E byte */
-         assign(E_byte, getByteFromReg(rt, 3));
+               if (mode64) {
+                  assign(t1, binop(Iop_CmpNE64,
+                                   binop(Iop_And64,
+                                         unop(Iop_ReinterpF64asI64, getDReg(ft)),
+                                         mkU64(1)),
+                                   mkU64(0)));
+               } else {
+                  assign(t1, binop(Iop_CmpNE32,
+                                   binop(Iop_And32,
+                                         unop(Iop_64to32,
+                                              unop(Iop_ReinterpF64asI64, getDReg(ft))),
+                                         mkU32(1)),
+                                   mkU32(0)));
+               }
 
-         /* t1 = addr */
-         t1 = newTemp(Ity_I32);
-         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+               dis_branch(False, mkexpr(t1), imm, bstmt);
+            } else {
+               ILLEGAL_INSTRUCTON;
+               break;
+            }
+         } else {
+            if (fmt == 0x15) { /* CMP.cond.d */
+               Bool comparison = True;
+               UInt signaling = CMPAFD;
+               DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
+               t0 = newTemp(Ity_I32);
 
-         /* t2 = word addr */
-         t2 = newTemp(Ity_I32);
-         assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+               /* Conditions starting with S should signal exception on QNaN inputs. */
+               switch (function) {
+                  case 0x08:  /* SAF */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x00: /* AF */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             binop(Iop_I64StoF64,
+                                   get_IR_roundingmode(), mkU64(0)));
+                     break;
+
+                  case 0x09: /* SUN */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x01: /* UN */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0))));
+                     break;
+
+                  case 0x19: /* SOR */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x11: /* OR */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL))));
+                     break;
+
+                  case 0x0A: /* SEQ */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x02: /* EQ */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0))));
+                     break;
+
+                  case 0x1A: /* SNEQ */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x12: /* NEQ */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL))));
+                     break;
+
+                  case 0x0B: /* SUEQ */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x03: /* UEQ */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x45)),
+                                                   unop(Iop_ReinterpI64asF64,
+                                                        mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(),
+                                                         mkU64(0)))));
+                     break;
+
+                  case 0x1B:  /* SNEQ */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x13:  /* NEQ */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x00)),
+                                                   unop(Iop_ReinterpI64asF64,
+                                                        mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(),
+                                                         mkU64(0)))));
+                     break;
+
+                  case 0x0C: /* SLT */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x04: /* LT */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0))));
+                     break;
+
+                  case 0x0D: /* SULT */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x05: /* ULT */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x45)),
+                                                   unop(Iop_ReinterpI64asF64,
+                                                        mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(),
+                                                         mkU64(0)))));
+                     break;
+
+                  case 0x0E: /* SLE */
+                     signaling = CMPSAFD; /* fallthrough */
+
+                  case 0x06: /* LE */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x40)),
+                                                   unop(Iop_ReinterpI64asF64,
+                                                        mkU64(0xFFFFFFFFFFFFFFFFULL)),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(),
+                                                         mkU64(0)))));
+                     break;
 
-         /* t3 = addr mod 4 */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+                  case 0x0F: /* SULE */
+                     signaling = CMPSAFD; /* fallthrough */
 
-#if defined (_MIPSEL)
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
-                                  mkU32(0x0),
-                                  mkU32(0x1)));
+                  case 0x07: /* ULE */
+                     assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+                     calculateFCSR(fs, ft, signaling, False, 2);
+                     putDReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
+                                        binop(Iop_I64StoF64,
+                                              get_IR_roundingmode(), mkU64(0)),
+                                        unop(Iop_ReinterpI64asF64,
+                                             mkU64(0xFFFFFFFFFFFFFFFFULL))));
+                     break;
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
-                                  mkU32(0x1),
-                                  mkU32(0x0)));
+                  default:
+                     comparison = False;
+               }
 
-         /* Store X_byte on the right place. */
-         store(mkexpr(t2), mkexpr(H_byte));
-         store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-         store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-         store(mkexpr(t1), mkexpr(E_byte));
+               if (comparison) {
+                  if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-#else    /* _MIPSEB */
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
-                                  mkU32(0x0),
-                                  mkU32(0x1)));
+                  break;
+               }
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
-                                  mkU32(0x2),
-                                  mkU32(0x3)));
+            } else if (fmt == 0x14) {
+               Bool comparison = True;
+               UInt signaling = CMPAFS;
+               DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
+               t0 = newTemp(Ity_I32);
 
-         store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
-         store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
-         store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
-         store(mkexpr(t1), mkexpr(E_byte));
+               /* Conditions starting with S should signal exception on QNaN inputs. */
+               switch (function) {
+                  case 0x08:  /* SAF */
+                     signaling = CMPSAFS; /* fallthrough */
 
-#endif
-      }
-      break;
+                  case 0x00: /* AF */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             mkWidenFromF32(tyF,
+                                            binop(Iop_I32StoF32,
+                                                  get_IR_roundingmode(), mkU32(0))));
+                     break;
 
-   case 0x2E:  /* SWR */
-      DIP("swr r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         IRTemp E_byte = newTemp(Ity_I8);
-         IRTemp F_byte = newTemp(Ity_I8);
-         IRTemp G_byte = newTemp(Ity_I8);
-         IRTemp H_byte = newTemp(Ity_I8);
-         IRTemp F_pos  = newTemp(Ity_I64);
-         IRTemp G_pos  = newTemp(Ity_I64);
+                  case 0x09: /* SUN */
+                     signaling = CMPSAFS; /* fallthrough */
 
-         /* H byte */
-         assign(H_byte, getByteFromReg(rt, 0));
-         /* G byte */
-         assign(G_byte, getByteFromReg(rt, 1));
-         /* F byte */
-         assign(F_byte, getByteFromReg(rt, 2));
-         /* E byte */
-         assign(E_byte, getByteFromReg(rt, 3));
+                  case 0x01: /* UN */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0)))));
+                     break;
+
+                  case 0x19: /* SOR */
+                     signaling = CMPSAFS; /* fallthrough */
+
+                  case 0x11: /* OR */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0))),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU)))));
+                     break;
+
+                  case 0x0A: /* SEQ */
+                     signaling = CMPSAFS; /* fallthrough */
+
+                  case 0x02: /* EQ */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0)))));
+                     break;
+
+                  case 0x1A: /* SNEQ */
+                     signaling = CMPSAFS; /* fallthrough */
+
+                  case 0x12: /* NEQ */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0))),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU)))));
+                     break;
+
+                  case 0x0B: /* SUEQ */
+                     signaling = CMPSAFS; /* fallthrough */
+
+                  case 0x03: /* UEQ */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x45)),
+                                                   mkWidenFromF32(tyF,
+                                                         unop(Iop_ReinterpI32asF32,
+                                                               mkU32(0xFFFFFFFFU))),
+                                                   mkWidenFromF32(tyF,
+                                                         binop(Iop_I32StoF32,
+                                                               get_IR_roundingmode(),
+                                                               mkU32(0))))));
+                     break;
 
-         /* t1 = addr */
-         t1 = newTemp(Ity_I64);
-         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+                  case 0x1B:  /* SNEQ */
+                     signaling = CMPSAFS; /* fallthrough */
 
-         /* t2 = word addr */
-         t2 = newTemp(Ity_I64);
-         assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+                  case 0x13:  /* NEQ */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x00)),
+                                                   mkWidenFromF32(tyF,
+                                                         unop(Iop_ReinterpI32asF32,
+                                                               mkU32(0xFFFFFFFFU))),
+                                                   mkWidenFromF32(tyF,
+                                                         binop(Iop_I32StoF32,
+                                                               get_IR_roundingmode(),
+                                                               mkU32(0))))));
+                     break;
 
-         /* t3 = addr mod 4 */
-         t3 = newTemp(Ity_I64);
-         assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+                  case 0x0C: /* SLT */
+                     signaling = CMPSAFS; /* fallthrough */
 
-#if defined (_MIPSEL)
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                                  mkU64(0x2),
-                                  mkU64(0x3)));
+                  case 0x04: /* LT */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0)))));
+                     break;
+
+                  case 0x0D: /* SULT */
+                     signaling = CMPSAFS; /* fallthrough */
+
+                  case 0x05: /* ULT */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x45)),
+                                                   mkWidenFromF32(tyF,
+                                                         unop(Iop_ReinterpI32asF32,
+                                                               mkU32(0xFFFFFFFFU))),
+                                                   mkWidenFromF32(tyF,
+                                                         binop(Iop_I32StoF32,
+                                                               get_IR_roundingmode(),
+                                                               mkU32(0))))));
+                     break;
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
-                                  mkU64(0x0),
-                                  mkU64(0x1)));
+                  case 0x0E: /* SLE */
+                     signaling = CMPSAFS; /* fallthrough */
 
-         /* Store X_byte on the right place. */
-         store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
-         store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
-         store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-         store(mkexpr(t1), mkexpr(H_byte));
+                  case 0x06: /* LE */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU))),
+                                        IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                         mkexpr(t0), mkU32(0x40)),
+                                                   mkWidenFromF32(tyF,
+                                                         unop(Iop_ReinterpI32asF32,
+                                                               mkU32(0xFFFFFFFFU))),
+                                                   mkWidenFromF32(tyF,
+                                                         binop(Iop_I32StoF32,
+                                                               get_IR_roundingmode(),
+                                                               mkU32(0))))));
+                     break;
 
-#else    /* _MIPSEB */
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
-                                  mkU64(0x1),
-                                  mkU64(0x0)));
+                  case 0x0F: /* SULE */
+                     signaling = CMPSAFS; /* fallthrough */
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
-                                  mkU64(0x0),
-                                  mkU64(0x1)));
+                  case 0x07: /* ULE */
+                     assign(t0, binop(Iop_CmpF32,
+                                      getLoFromF64(Ity_F64, getFReg(fs)),
+                                      getLoFromF64(Ity_F64, getFReg(ft))));
+                     calculateFCSR(fs, ft, signaling, True, 2);
+                     putFReg(fd,
+                             IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
+                                        mkWidenFromF32(tyF,
+                                                       binop(Iop_I32StoF32,
+                                                             get_IR_roundingmode(),
+                                                             mkU32(0))),
+                                        mkWidenFromF32(tyF,
+                                                       unop(Iop_ReinterpI32asF32,
+                                                            mkU32(0xFFFFFFFFU)))));
+                     break;
 
-         /* Store X_byte on the right place. */
-         store(mkexpr(t2), mkexpr(E_byte));
-         store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
-         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-         store(mkexpr(t1), mkexpr(H_byte));
-#endif
-      } else {
-         IRTemp E_byte = newTemp(Ity_I8);
-         IRTemp F_byte = newTemp(Ity_I8);
-         IRTemp G_byte = newTemp(Ity_I8);
-         IRTemp H_byte = newTemp(Ity_I8);
-         IRTemp F_pos  = newTemp(Ity_I32);
-         IRTemp G_pos  = newTemp(Ity_I32);
+                  default:
+                     comparison = False;
+               }
 
-         /* H byte */
-         assign(H_byte, getByteFromReg(rt, 0));
-         /* G byte */
-         assign(G_byte, getByteFromReg(rt, 1));
-         /* F byte */
-         assign(F_byte, getByteFromReg(rt, 2));
-         /* E byte */
-         assign(E_byte, getByteFromReg(rt, 3));
+               if (comparison) {
+                  if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     ILLEGAL_INSTRUCTON
+                  }
 
-         /* t1 = addr */
-         t1 = newTemp(Ity_I32);
-         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+                  break;
+               }
+            }
 
-         /* t2 = word addr */
-         t2 = newTemp(Ity_I32);
-         assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+            switch (function) {
+               case 0x04: {  /* 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;
+                     }
 
-         /* t3 = addr mod 4 */
-         t3 = newTemp(Ity_I32);
-         assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+                     case 0x11: {  /* D */
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
+                        break;
+                     }
 
-#if defined (_MIPSEL)
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
-                                  mkU32(0x2),
-                                  mkU32(0x3)));
+                     default:
+                        return -1;
+                  }
+               }
+               break;    /* SQRT.fmt */
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
-                                  mkU32(0x0),
-                                  mkU32(0x1)));
+               case 0x05:  /* ABS.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("abs.s f%u, f%u", fd, fs);
+                        putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
+                                                             getLoFromF64(tyF, getFReg(fs)))));
+                        break;
 
-         /* Store X_byte on the right place. */
-         store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
-         store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
-         store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-         store(mkexpr(t1), mkexpr(H_byte));
+                     case 0x11:  /* D  */
+                        DIP("abs.d f%u, f%u", fd, fs);
+                        putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
+                        break;
 
-#else    /* _MIPSEB */
-         /* Calculate X_byte position. */
-         assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
-                                  mkU32(0x1),
-                                  mkU32(0x0)));
+                     default:
+                        return -1;
+                  }
 
-         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
-                                  mkU32(0x0),
-                                  mkU32(0x1)));
+                  break;  /* ABS.fmt */
 
-         /* Store X_byte on the right place. */
-         store(mkexpr(t2), mkexpr(E_byte));
-         store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
-         store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
-         store(mkexpr(t1), mkexpr(H_byte));
-#endif
-      }
-      break;
+               case 0x02:  /* MUL.fmt */
+                  switch (fmt) {
+                     case 0x11: {  /* D */
+                        DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
+                                          getDReg(ft)));
+                        break;
+                     }
 
-   case 0x1C:  /* Special2 */
-      switch (function) {
-         /* Cavium Specific instructions */
-         case 0x03: case 0x32: case 0x33:  /* DMUL, CINS , CINS32 */
-         case 0x3A: case 0x3B: case 0x2B:  /* EXT,  EXT32, SNE    */
-         /* CVM Compare Instructions */
-         case 0x2A: case 0x2E: case 0x2F:  /* SEQ,  SEQI,  SNEI   */
-         /* CPU Load, Store, Memory, and Control Instructions */
-         case 0x18: case 0x19:             /* SAA, SAAD */
-         case 0x1F:                        /* LAA, LAAD, LAI, LAID */
-         case 0x28: case 0x2C: case 0x2D:  /* BADDU, POP, DPOP */
-            if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-               if (dis_instr_CVM(cins))
-                  break;
-               goto decode_failure;
-            } else {
-               goto decode_failure;
-            }
-         break;
+                     case 0x10: {  /* S */
+                        DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
+                                                              getLoFromF64(tyF, getFReg(fs)),
+                                                              getLoFromF64(tyF, getFReg(ft)))));
+                        break;
+                     }
 
-         case 0x02: {  /* MUL */
-            DIP("mul r%u, r%u, r%u", rd, rs, rt);
-            if (mode64) {
-               IRTemp tmpRs32 = newTemp(Ity_I32);
-               IRTemp tmpRt32 = newTemp(Ity_I32);
-               IRTemp tmpRes = newTemp(Ity_I32);
+                     default:
+                        return -1;
+                  }
 
-               assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
-               assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-               assign(tmpRes, binop(Iop_Mul32,
-                                    mkexpr(tmpRs32), mkexpr(tmpRt32)));
-               putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
-            } else
-               putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
-            break;
-         }
+                  break;  /* MUL.fmt */
 
-         case 0x00: {  /* MADD */
-            if (mode64) {
-               DIP("madd r%u, r%u", rs, rt);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I64);
-               t4 = newTemp(Ity_I64);
-               t5 = newTemp(Ity_I64);
-               t6 = newTemp(Ity_I32);
+               case 0x03:  /* DIV.fmt */
+                  switch (fmt) {
+                     case 0x11: {  /* D */
+                        DIP("div.d f%u, f%u, f%u", fd, fs, ft);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
+                                          getDReg(ft)));
+                        break;
+                     }
 
-               assign(t1, mkNarrowTo32(ty, getHI()));
-               assign(t2, mkNarrowTo32(ty, getLO()));
+                     case 0x10: {  /* S */
+                        DIP("div.s f%u, f%u, f%u", fd, fs, ft);
+                        calculateFCSR(fs, ft, DIVS, False, 2);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+                                                              getLoFromF64(tyF, getFReg(fs)),
+                                                              getLoFromF64(tyF, getFReg(ft)))));
+                        break;
+                     }
 
-               assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
-                                             mkNarrowTo32(ty, getIReg(rt))));
+                     default:
+                        return -1;
+                  }
 
-               assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
-               assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
+                  break;  /* DIV.fmt */
 
-               putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
-               putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
-            } else {
-               if ( (1 <= ac) && ( 3 >= ac) ) {
-                  if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                     /* If DSP is present -> DSP ASE MADD */
-                     UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                     if (0 != retVal ) {
-                        goto decode_failure_dsp;
+               case 0x01:  /* SUB.fmt */
+                  switch (fmt) {
+                     case 0x11: {  /* D */
+                        DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
+                        calculateFCSR(fs, ft, SUBD, False, 2);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
+                                          getDReg(ft)));
+                        break;
                      }
-                     break;
-                  } else {
-                     goto decode_failure_dsp;
+
+                     case 0x10: {  /* S */
+                        DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
+                        calculateFCSR(fs, ft, SUBS, True, 2);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
+                                                              getLoFromF64(tyF, getFReg(fs)),
+                                                              getLoFromF64(tyF, getFReg(ft)))));
+                        break;
+                     }
+
+                     default:
+                        return -1;
                   }
-               } else {
-                  DIP("madd r%u, r%u", rs, rt);
-                  t1 = newTemp(Ity_I32);
-                  t2 = newTemp(Ity_I32);
-                  t3 = newTemp(Ity_I64);
-                  t4 = newTemp(Ity_I32);
-                  t5 = newTemp(Ity_I32);
-                  t6 = newTemp(Ity_I32);
 
-                  assign(t1, getHI());
-                  assign(t2, getLO());
+                  break;  /* SUB.fmt */
 
-                  assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+               case 0x06:  /* MOV.fmt */
+                  switch (fmt) {
+                     case 0x11:  /* D */
+                        DIP("mov.d f%u, f%u", fd, fs);
 
-                  assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
-                                                               mkexpr(t3))));
+                        if (fp_mode64) {
+                           putDReg(fd, getDReg(fs));
+                        } else {
+                           putFReg(fd, getFReg(fs));
+                           putFReg(fd + 1, getFReg(fs + 1));
+                        }
 
-                  assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
-                                              unop(Iop_64to32, mkexpr(t3)))));
-                  assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+                        break;
 
-                  putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
-                                                          mkexpr(t3))));
-                  putLO(mkexpr(t4));
-                  break;
-               }
-            }
-            break;
-         }
+                     case 0x10:  /* S */
+                        DIP("mov.s f%u, f%u", fd, fs);
+                        putFReg(fd, getFReg(fs));
+                        break;
 
-      case 0x01: {  /* MADDU */
-         if (mode64) {
-            DIP("maddu r%u, r%u", rs, rt);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I64);
-            t4 = newTemp(Ity_I64);
-            t5 = newTemp(Ity_I64);
-            t6 = newTemp(Ity_I32);
+                     default:
+                        return -1;
+                  }
 
-            assign(t1, mkNarrowTo32(ty, getHI()));
-            assign(t2, mkNarrowTo32(ty, getLO()));
+                  break;  /* MOV.fmt */
 
-            assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
-                                          mkNarrowTo32(ty, getIReg(rt))));
+               case 0x07:  /* NEG.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("neg.s f%u, f%u", fd, fs);
+                        putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
+                                                             getLoFromF64(tyF, getFReg(fs)))));
+                        break;
 
-            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
-            assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
+                     case 0x11:  /* D */
+                        DIP("neg.d f%u, f%u", fd, fs);
+                        putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
+                        break;
 
-            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
-            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
-         } else {
-            if ( (1 <= ac) && ( 3 >= ac) ) {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  /* If DSP is present -> DSP ASE MADDU */
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+                     default:
+                        return -1;
                   }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-            } else {
-               DIP("maddu r%u, r%u", rs, rt);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I64);
-               t4 = newTemp(Ity_I32);
-               t5 = newTemp(Ity_I32);
-               t6 = newTemp(Ity_I32);
 
-               assign(t1, getHI());
-               assign(t2, getLO());
+                  break;  /* NEG.fmt */
 
-               assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+               case 0x08:  /* ROUND.L.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("round.l.s f%u, f%u", fd, fs);
 
-               assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
-                                                            mkexpr(t3))));
-               assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
-                                           unop(Iop_64to32, mkexpr(t3)))));
-               assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, ROUNDLS, True, 1);
+                           t0 = newTemp(Ity_I64);
 
-               putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
-                                                      mkexpr(t3))));
-               putLO(mkexpr(t4));
-               break;
-            }
-         }
-         break;
-      }
+                           assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
+                                            getLoFromF64(Ity_F64, getFReg(fs))));
 
-      case 0x04: {  /* MSUB */
-         if (mode64) {
-            DIP("msub r%u, r%u", rs, rt);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I64);
-            t4 = newTemp(Ity_I64);
-            t5 = newTemp(Ity_I64);
-            t6 = newTemp(Ity_I32);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            assign(t1, mkNarrowTo32(ty, getHI()));
-            assign(t2, mkNarrowTo32(ty, getLO()));
+                        break;
 
-            assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
-                                          mkNarrowTo32(ty, getIReg(rt))));
+                     case 0x11:  /* D */
+                        DIP("round.l.d f%u, f%u", fd, fs);
 
-            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
-            assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, ROUNDLD, False, 1);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            binop(Iop_F64toI64S,
+                                                  mkU32(0x0),
+                                                  getDReg(fs))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
-            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
-         } else {
-            if ( (1 <= ac) && ( 3 >= ac) ) {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  /* If DSP is present -> DSP ASE MSUB */
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
-                  }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-            } else {
-               DIP("msub r%u, r%u", rs, rt);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I64);
-               t4 = newTemp(Ity_I32);
-               t5 = newTemp(Ity_I1);
-               t6 = newTemp(Ity_I32);
+                        break;
 
-               assign(t1, getHI());
-               assign(t2, getLO());
+                     default:
+                        return -1;
 
-               assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
-               assign(t4, unop(Iop_64to32, mkexpr(t3)));  /* new lo */
+                  }
 
-               /* if lo<lo(mul) hi = hi - 1 */
-               assign(t5, binop(Iop_CmpLT32U,
-                                 mkexpr(t2),
-                                 mkexpr(t4)));
+                  break;  /* ROUND.L.fmt */
 
-               assign(t6, IRExpr_ITE(mkexpr(t5),
-                                       binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
-                                       mkexpr(t1)));
+               case 0x09:  /* TRUNC.L.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("trunc.l.s f%u, f%u", fd, fs);
 
-               putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
-                                                      mkexpr(t3))));
-               putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
-               break;
-            }
-         }
-         break;
-      }
+                        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))));
 
-      case 0x05: {  /* MSUBU */
-         if (mode64) {
-            DIP("msubu r%u, r%u", rs, rt);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I64);
-            t4 = newTemp(Ity_I64);
-            t5 = newTemp(Ity_I64);
-            t6 = newTemp(Ity_I32);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            assign(t1, mkNarrowTo32(ty, getHI()));
-            assign(t2, mkNarrowTo32(ty, getLO()));
+                        break;
 
-            assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
-                                          mkNarrowTo32(ty, getIReg(rt))));
+                     case 0x11:  /* D */
+                        DIP("trunc.l.d f%u, f%u", fd, fs);
 
-            assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
-            assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, TRUNCLD, False, 1);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            binop(Iop_F64toI64S,
+                                                  mkU32(0x3),
+                                                  getDReg(fs))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
-            putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
-         } else {
-            if ( (1 <= ac) && ( 3 >= ac) ) {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  /* If DSP is present -> DSP ASE MSUBU */
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+                        break;
+
+                     default:
+                        return -1;
                   }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-            } else {
-               DIP("msubu r%u, r%u", rs, rt);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I64);
-               t4 = newTemp(Ity_I32);
-               t5 = newTemp(Ity_I1);
-               t6 = newTemp(Ity_I32);
 
-               assign(t1, getHI());
-               assign(t2, getLO());
+                  break;  /* TRUNC.L.fmt */
 
-               assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
-               assign(t4, unop(Iop_64to32, mkexpr(t3)));  /* new lo */
+               case 0x15:  /* RECIP.fmt */
+                  switch (fmt) {
+                     case 0x10: {  /* S */
+                        DIP("recip.s f%u, f%u", fd, fs);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
+                                                              rm, unop(Iop_ReinterpI32asF32,
+                                                                    mkU32(ONE_SINGLE)), getLoFromF64(tyF,
+                                                                          getFReg(fs)))));
+                        break;
+                     }
 
-               /* if lo<lo(mul) hi = hi - 1 */
-               assign(t5, binop(Iop_CmpLT32U,
-                                 mkexpr(t2),
-                                 mkexpr(t4)));
+                     case 0x11: {  /* D */
+                        DIP("recip.d f%u, f%u", fd, fs);
+                        IRExpr *rm = get_IR_roundingmode();
+                        /* putDReg(fd, 1.0/getDreg(fs)); */
+                        putDReg(fd, triop(Iop_DivF64, rm,
+                                          unop(Iop_ReinterpI64asF64,
+                                               mkU64(ONE_DOUBLE)), getDReg(fs)));
+                        break;
+                     }
 
-               assign(t6, IRExpr_ITE(mkexpr(t5),
-                                    binop(Iop_Sub32,
-                                          mkexpr(t1),
-                                          mkU32(0x1)),
-                                    mkexpr(t1)));
+                     default:
+                        return -1;
 
-               putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
-                                                      mkexpr(t3))));
-               putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
-               break;
-            }
-         }
-         break;
-      }
+                  }
 
-      case 0x6:  /* dmul MIPS64 - Netlogic */
-         DIP("dmul r%u, r%u, r%u", rd, rs, rt);
-         t0 = newTemp(Ity_I128);
+                  break;  /* RECIP.fmt */
 
-         assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
+               case 0x13:  /* MOVN.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
+                        t1 = newTemp(Ity_I1);
 
-         putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
-         break;
+                        if (mode64)
+                           assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+                        else
+                           assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
 
-      case 0x10:  /* LDADDW - Swap Word - Netlogic */
-         DIP("ldaddw r%u, r%u", rt, rs);
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         t2 = newTemp(Ity_I32);
-         t3 = newTemp(Ity_I64);
-         t4 = newTemp(Ity_I32);
-         t5 = newTemp(Ity_I32);
-         t6 = newTemp(Ity_I32);
+                        putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
+                        break;
 
-         /* v = GPR[rt] */
-         assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+                     case 0x11:  /* D */
+                        DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
+                        t1 = newTemp(Ity_I1);
 
-         /* GPR[rt] = memory[base]; */
-         assign(t1, load(Ity_I32, getIReg(rs)));
-         putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+                        if (mode64)
+                           assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+                        else
+                           assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
 
-         /* memory[base] = memory[base] + v; */
-         store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
-         break;
+                        putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
+                        break;
 
-      case 0x12:  /* LDADDD - Swap Word - Netlogic */
-         DIP("ldaddw r%u, r%u", rt, rs);
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I64);
+                     default:
+                        return -1;
+                  }
 
-         /*  v = GPR[rt] */
-         assign(t0, getIReg(rt));
+                  break;  /* MOVN.fmt */
 
-         /* GPR[rt] = memory[base]; */
-         assign(t1, load(Ity_I64, getIReg(rs)));
-         putIReg(rt, mkexpr(t1));
+               case 0x12:  /* MOVZ.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
+                        t1 = newTemp(Ity_I1);
 
-         /* memory[base] = memory[base] + v; */
-         store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
-         break;
+                        if (mode64)
+                           assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+                        else
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
 
-      case 0x14:  /* SWAPW - Swap Word - Netlogic */
-         DIP("swapw r%u, r%u", rt, rs);
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         assign(t0, mkNarrowTo32(ty, getIReg(rt)));
-         assign(t1, load(Ity_I32, getIReg(rs)));
-         putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
-         store(getIReg(rs), mkexpr(t0));
-         break;
+                        putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
+                        break;
 
-      case 0x16:  /* SWAPD - Swap Double - Netlogic */
-         DIP("swapw r%u, r%u", rt, rs);
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I64);
-         assign(t0, getIReg(rt));
-         assign(t1, load(Ity_I64, getIReg(rs)));
-         putIReg(rt, mkexpr(t1));
-         store(getIReg(rs), mkexpr(t0));
-         break;
+                     case 0x11:  /* D */
+                        DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
+                        t1 = newTemp(Ity_I1);
 
-      case 0x20: {  /* CLZ */
-         DIP("clz r%u, r%u", rd, rs);
-         if (mode64) {
-            IRTemp tmpClz32 = newTemp(Ity_I32);
-            IRTemp tmpRs32 = newTemp(Ity_I32);
+                        if (mode64)
+                           assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+                        else
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
 
-            assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
-            assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
-            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
-         } else {
-            t1 = newTemp(Ity_I1);
-            assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
-            putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                   mkU32(0x00000020),
-                                   unop(Iop_Clz32, getIReg(rs))));
-         }
-         break;
-      }
+                        putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
+                        break;
 
-      case 0x21: {  /* CLO */
-         DIP("clo r%u, r%u", rd, rs);
-         if (mode64) {
-            IRTemp tmpClo32 = newTemp(Ity_I32);
-            IRTemp tmpRs32 = newTemp(Ity_I32);
-            assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+                     default:
+                        return -1;
+                  }
 
-            t1 = newTemp(Ity_I1);
-            assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
-            assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
-                      mkU32(0x00000020),
-                      unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
+                  break;  /* MOVZ.fmt */
 
-            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
-            break;
-         } else {
-            t1 = newTemp(Ity_I1);
-            assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
-            putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                   mkU32(0x00000020),
-                                   unop(Iop_Clz32,
-                                        unop(Iop_Not32, getIReg(rs)))));
-            break;
-         }
-      }
+               case 0x11:  /* MOVT.fmt */
+                  if (tf == 1) {
+                     UInt mov_cc = get_mov_cc(cins);
 
-      case 0x24:  /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
-         DIP("dclz r%u, r%u", rd, rs);
-         t1 = newTemp(Ity_I1);
-         assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
-         putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                     mkU64(0x00000040),
-                     unop(Iop_Clz64, getIReg(rs))));
-         break;
+                     switch (fmt) {  /* MOVCF = 010001 */
+                        case 0x11:  /* D */
+                           DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
+                           t1 = newTemp(Ity_I1);
+                           t2 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_I1);
+                           t4 = newTemp(Ity_F64);
 
-      case 0x25:  /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
-         DIP("dclo r%u, r%u", rd, rs);
-         t1 = newTemp(Ity_I1);
-         assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
-                                        mkU64(0xffffffffffffffffULL)));
-         putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                mkU64(0x40),
-                                unop(Iop_Clz64, unop(Iop_Not64,
-                                                     getIReg(rs)))));
-         break;
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                                       mkU32(0x1))
+                                                ));
+
+                           assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+                           assign(t4, IRExpr_ITE(mkexpr(t3),
+                                                 getDReg(fs), getDReg(fd)));
+                           putDReg(fd, mkexpr(t4));
+                           break;
 
-      default:
-         goto decode_failure;
-      }
-      break;
-
-   case 0x1F:  /* Special3 */
-      switch (function) {
-         case 0x01: {
-            /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
-            msb = get_msb(cins);
-            lsb = get_lsb(cins);
-            size = msb + 1;
-            UInt srcPos = lsb;
-            UInt dstSz = msb + 33;
-            t1 = newTemp(Ity_I64);
-            DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
+                        case 0x10:  /* S */
+                           DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
+                           t1 = newTemp(Ity_I1);
+                           t2 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_I1);
+                           t4 = newTemp(Ity_F64);
+                           t5 = newTemp(Ity_F64);
+                           t6 = newTemp(Ity_F64);
+                           t7 = newTemp(Ity_I64);
+
+                           if (fp_mode64) {
+                              assign(t5, getFReg(fs));
+                              assign(t6, getFReg(fd));
+                           } else {
+                              assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+                              assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+                           }
 
-            UChar lsAmt = 64 - (srcPos + dstSz);  /* left shift amount; */
-            UChar rsAmt = 64 - dstSz;  /* right shift amount; */
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                                       mkU32(0x1))
+                                                ));
+
+                           assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+                           assign(t4, IRExpr_ITE(mkexpr(t3),
+                                                 mkexpr(t5), mkexpr(t6)));
+
+                           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(Ity_I64, unop(Iop_64to32,
+                                                                     unop(Iop_ReinterpF64asI64, mkexpr(t4))),
+                                                       True));
+
+                              putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
+                           } else
+                              putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                                mkexpr(t4)));
 
-            assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
-            putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+                           break;
 
-            break;
-         }
-         case 0x02: {
-            /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
-            msb = get_msb(cins);
-            lsb = get_lsb(cins);
-            size = msb + 1;
-            UInt srcPos = lsb + 32;
-            UInt dstSz = msb + 1;
-            DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
-            t1 = newTemp(Ity_I64);
+                        default:
+                           return -1;
+                     }
+                  } else if (tf == 0) { /* MOVF.fmt */
+                     UInt mov_cc = get_mov_cc(cins);
+
+                     switch (fmt) { /* MOVCF = 010001 */
+                        case 0x11:  /* D */
+                           DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
+                           t1 = newTemp(Ity_I1);
+                           t2 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_I1);
+                           t4 = newTemp(Ity_F64);
+
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                                       mkU32(0x1))
+                                                ));
+
+                           assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+                           assign(t4, IRExpr_ITE(mkexpr(t3),
+                                                 getDReg(fs), getDReg(fd)));
+                           putDReg(fd, mkexpr(t4));
+                           break;
+
+                        case 0x10:  /* S */
+                           DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
+                           t1 = newTemp(Ity_I1);
+                           t2 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_I1);
+                           t4 = newTemp(Ity_F64);
+                           t5 = newTemp(Ity_F64);
+                           t6 = newTemp(Ity_F64);
+
+                           if (fp_mode64) {
+                              assign(t5, getFReg(fs));
+                              assign(t6, getFReg(fd));
+                           } else {
+                              assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+                              assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+                           }
 
-            vassert(srcPos >= 32 && srcPos < 64);
-            vassert(dstSz > 0 && dstSz <= 32);
-            vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
+                           assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
+                                                       mkU32(0x1))
+                                                ));
+
+                           assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+                           assign(t4, IRExpr_ITE(mkexpr(t3),
+                                                 mkexpr(t5), mkexpr(t6)));
+
+                           if (fp_mode64) {
+                              IRTemp f = newTemp(Ity_F64);
+                              IRTemp fd_hi = newTemp(Ity_I32);
+                              t7 = newTemp(Ity_I64);
+                              assign(f, getFReg(fd));
+                              assign(fd_hi, unop(Iop_64HIto32,
+                                                 unop(Iop_ReinterpF64asI64, mkexpr(f))));
+                              assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
+                                                                     unop(Iop_ReinterpF64asI64, mkexpr(t4))),
+                                                       True));
+
+                              putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
+                           } else
+                              putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                                mkexpr(t4)));
 
-            UChar lsAmt = 64 - (srcPos + dstSz);  /* left shift amount; */
-            UChar rsAmt = 64 - dstSz;  /* right shift amount; */
+                           break;
 
-            assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
-            putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
-            break;
-         }
-         case 0x05: {
-            /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
-            msb = get_msb(cins);
-            lsb = get_lsb(cins);
-            size = msb + 1;
-            UInt dstPos = lsb;
-            UInt srcSz = msb - lsb + 33;
-            t1 = newTemp(ty);
-            t2 = newTemp(ty);
-            t3 = newTemp(ty);
-            t4 = newTemp(ty);
-            IRTemp tmpT1 = newTemp(ty);
-            IRTemp tmpT2 = newTemp(ty);
-            IRTemp tmpT3 = newTemp(ty);
-            IRTemp tmpT4 = newTemp(ty);
-            IRTemp tmpT5 = newTemp(ty);
-            IRTemp tmpT6 = newTemp(ty);
-            IRTemp tmpT7 = newTemp(ty);
-            IRTemp tmpRs = newTemp(ty);
-            IRTemp tmpRt = newTemp(ty);
-            IRTemp tmpRd = newTemp(ty);
-
-            assign(tmpRs, getIReg(rs));
-            assign(tmpRt, getIReg(rt));
-            DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
-
-            UChar lsAmt = dstPos + srcSz - 1;   /* left shift amount; */
-            UChar rsAmt = dstPos + srcSz - 1;   /* right shift amount; */
-
-            assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
-            assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
-            assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
-            assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
-
-            lsAmt = 63 - dstPos; /* left shift amount; */
-            rsAmt = 63 - dstPos; /* right shift amount; */
-
-            assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
-            assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
-            assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
-            assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
-
-            /* extract size from src register */
-            lsAmt = 64 - srcSz;  /* left shift amount; */
-            rsAmt = 64 - (lsb + srcSz);   /* right shift amount; */
-
-            assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
-            assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
-
-            assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
-            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
-            putIReg(rt, mkexpr(tmpRd));
-            break;
-         }
-         case 0x06: {
-            /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
-            msb = get_msb(cins);
-            lsb = get_lsb(cins);
-            size = msb + 1;
-            UInt dstPos = lsb + 32;
-            UInt srcSz = msb - lsb + 1;
-            IRTemp tmpT1 = newTemp(ty);
-            IRTemp tmpT2 = newTemp(ty);
-            IRTemp tmpT3 = newTemp(ty);
-            IRTemp tmpT4 = newTemp(ty);
-            IRTemp tmpT5 = newTemp(ty);
-            IRTemp tmpT6 = newTemp(ty);
-            IRTemp tmpT7 = newTemp(ty);
-            IRTemp tmpT8 = newTemp(ty);
-            IRTemp tmpT9 = newTemp(ty);
-            IRTemp tmpRs = newTemp(ty);
-            IRTemp tmpRt = newTemp(ty);
-            IRTemp tmpRd = newTemp(ty);
-
-            assign(tmpRs, getIReg(rs));
-            assign(tmpRt, getIReg(rt));
-            DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
-
-            UChar lsAmt = 64 - srcSz;  /* left shift amount; */
-            UChar rsAmt = 64 - (dstPos + srcSz);  /* right shift amount; */
-            assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
-            assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
-
-            lsAmt = 64 - dstPos;  /* left shift amount; */
-            rsAmt = 64 - dstPos;  /* right shift amount; */
-            assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
-            assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
-
-            lsAmt = dstPos;  /* left shift amount; */
-            rsAmt = srcSz;  /* right shift amount; */
-            assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
-            assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
-
-            assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
-            assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
-
-            assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
-            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
-            putIReg(rt, mkexpr(tmpRd));
-            break;
-         }
-         case 0x07: {
-            /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
-            IRTemp tmp1 = newTemp(ty);
-            IRTemp tmpT1 = newTemp(ty);
-            IRTemp tmpT2 = newTemp(ty);
-            IRTemp tmpT3 = newTemp(ty);
-            IRTemp tmpT4 = newTemp(ty);
-            IRTemp tmpT5 = newTemp(ty);
-            IRTemp tmpT6 = newTemp(ty);
-            IRTemp tmpT7 = newTemp(ty);
-            IRTemp tmpT8 = newTemp(ty);
-            IRTemp tmpT9 = newTemp(ty);
-            IRTemp tmp = newTemp(ty);
-            IRTemp tmpRs = newTemp(ty);
-            IRTemp tmpRt = newTemp(ty);
-            IRTemp tmpRd = newTemp(ty);
-
-            assign(tmpRs, getIReg(rs));
-            assign(tmpRt, getIReg(rt));
-
-            msb = get_msb(cins);
-            lsb = get_lsb(cins);
-            size = msb + 1;
-            DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
-                msb - lsb + 1);
-            UChar lsAmt = 63 - lsb;  /* left shift amount; */
-            UChar rsAmt = 63 - lsb;  /* right shift amount; */
-            assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
-            assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
-            assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
-            assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
-
-            lsAmt = msb;  /* left shift amount; */
-            rsAmt = 1;  /*right shift amount; */
-            assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
-            assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
-            assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
-            assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
-
-            lsAmt = 64 - (msb - lsb + 1);  /* left shift amount; */
-            rsAmt = 64 - (msb + 1);  /* right shift amount; */
-            assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
-            assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
-
-            assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
-            assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
-            putIReg(rt, mkexpr(tmpRd));
-            break;
-         }
-      case 0x24:  /* DBSHFL */
-         lsb = get_lsb(cins);
-         IRTemp tmpRs = newTemp(ty);
-         IRTemp tmpRt = newTemp(ty);
-         IRTemp tmpRd = newTemp(ty);
-         assign(tmpRs, getIReg(rs));
-         assign(tmpRt, getIReg(rt));
-         switch (lsb) {
-            case 0x02: {  /* DSBH */
-               DIP("dsbh r%u, r%u", rd, rt);
-               IRTemp tmpT1 = newTemp(ty);
-               IRTemp tmpT2 = newTemp(ty);
-               IRTemp tmpT3 = newTemp(ty);
-               IRTemp tmpT4 = newTemp(ty);
-               IRTemp tmpT5 = newTemp(Ity_I64);
-               IRTemp tmpT6 = newTemp(ty);
-               assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
-               assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
-               assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
-               assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
-               assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
-               assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
-               assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
-               putIReg(rd, mkexpr(tmpRd));
-               break;
-            }
-            case 0x05: {  /* DSHD */
-               DIP("dshd r%u, r%u\n", rd, rt);
-               IRTemp tmpT1 = newTemp(ty);
-               IRTemp tmpT2 = newTemp(ty);
-               IRTemp tmpT3 = newTemp(ty);
-               IRTemp tmpT4 = newTemp(ty);
-               IRTemp tmpT5 = newTemp(Ity_I64);
-               IRTemp tmpT6 = newTemp(ty);
-               IRTemp tmpT7 = newTemp(ty);
-               IRTemp tmpT8 = newTemp(ty);
-               IRTemp tmpT9 = newTemp(ty);
-               assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
-               assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
-               assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
-               assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
-               assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
-               assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
-               assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
-               assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
-               assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
-               assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
-               putIReg(rd, mkexpr(tmpRd));
-               break;
-            }
-               case 0x08 ... 0x0f: { /* DALIGN */
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                     DIP("daling r%u, r%u, r%u, %u", rd, rs, rt,  lsb & 0x7);
-                     UInt bp = (lsb & 0x7) << 3;
-                     if (bp) {
-                        putIReg(rd, binop(Iop_Or64,
-                                          binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
-                                          binop(Iop_Shr64,
-                                                getIReg(rs), mkU8(64 - bp))));
-                     } else
-                        putIReg(rd, getIReg(rt));
-                  } else {
-                     ILLEGAL_INSTRUCTON;
+                        default:
+                           return -1;
+                     }
                   }
-                  break;
-               }
 
-               case 0: /* DBITSWAP */
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                     DIP("dbitswap r%u, r%u", rd, rt);
-                     putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
-                  } else {
-                     ILLEGAL_INSTRUCTON;
-                  }
-                  break;
-         default:
-            vex_printf("\nop6o10 = %u", lsb);
-            goto decode_failure;;
-         }
-         break;
-      case 0x3B: /* RDHWR */
-         DIP("rdhwr r%u, r%u", rt, rd);
-         if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
-             VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
-             (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
-            if (rd == 29) {
-               putIReg(rt, getULR());
-            } else if (rd <= 3
-                       || (rd == 31
-                           && VEX_MIPS_COMP_ID(archinfo->hwcaps)
-                                                    == VEX_PRID_COMP_CAVIUM)) {
-               IRExpr** arg = mkIRExprVec_1(mkU32(rd));
-               IRTemp   val  = newTemp(ty);
-               IRDirty *d = unsafeIRDirty_1_N(val,
-                                              0,
-                                              "mips_dirtyhelper_rdhwr",
-                                              &mips_dirtyhelper_rdhwr,
-                                              arg);
-               stmt(IRStmt_Dirty(d));
-               putIReg(rt, mkexpr(val));
-            } else
-               goto decode_failure;
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      case 0x04:  /* INS */
-         msb = get_msb(cins);
-         lsb = get_lsb(cins);
-         size = msb - lsb + 1;
-         DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
+                  break;  /* MOVT.fmt */
 
-         vassert(lsb + size <= 32);
-         vassert(lsb + size > 0);
+               case 0x00:  /* ADD.fmt */
+                  switch (fmt) {
+                     case 0x10: {  /* S */
+                        DIP("add.s f%u, f%u, f%u", fd, fs, ft);
+                        calculateFCSR(fs, ft, ADDS, True, 2);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
+                                                              getLoFromF64(tyF, getFReg(fs)),
+                                                              getLoFromF64(tyF, getFReg(ft)))));
+                        break;
+                     }
 
-         /* put size bits from rs at the pos in temporary */
-         t0 = newTemp(Ity_I32);
-         t3 = newTemp(Ity_I32);
-         /* shift left for 32 - size to clear leading bits and get zeros
-            at the end */
-         assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
-                          mkU8(32 - size)));
-         /* now set it at pos */
-         t1 = newTemp(Ity_I32);
-         assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
+                     case 0x11: {  /* D */
+                        DIP("add.d f%u, f%u, f%u", fd, fs, ft);
+                        calculateFCSR(fs, ft, ADDD, False, 2);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
+                        break;
+                     }
 
-         if (lsb > 0) {
-            t2 = newTemp(Ity_I32);
-            /* clear everything but lower pos bits from rt */
-            assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
-                             mkU8(32 - lsb)));
-            assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
-         } else
-            assign(t3, mkU32(0));
+                     case 0x04:  /* MTC1 (Move Word to Floating Point) */
+                        DIP("mtc1 r%u, f%u", rt, fs);
 
-         if (msb < 31) {
-            t4 = newTemp(Ity_I32);
-            /* clear everything but upper msb + 1 bits from rt */
-            assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
-                             mkU8(msb + 1)));
-            t5 = newTemp(Ity_I32);
-            assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I32);
+                           t1 = newTemp(Ity_F32);
+                           assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+                           assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
 
-            /* now combine these registers */
-            if (lsb > 0) {
-               t6 = newTemp(Ity_I32);
-               assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
-               putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
-                                                   mkexpr(t3)), True));
-            } else {
-               putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
-                                                   mkexpr(t5)), True));
-            }
-         } else {
-            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
-                                                mkexpr(t3)), True));
-         }
-         break;
+                           putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
+                        } else
+                           putFReg(fs, unop(Iop_ReinterpI32asF32,
+                                            mkNarrowTo32(ty, getIReg(rt))));
 
-      case 0x00:  /* EXT */
-         msb = get_msb(cins);
-         lsb = get_lsb(cins);
-         size = msb + 1;
-         DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
-         vassert(lsb + size <= 32);
-         vassert(lsb + size > 0);
-         /* put size bits from rs at the top of in temporary */
-         if (lsb + size < 32) {
-            t0 = newTemp(Ity_I32);
-            assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
-                             mkU8(32 - lsb - size)));
+                        break;
 
-            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
-                                                mkU8(32 - size)), True));
-         } else {
-            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
-                                                mkNarrowTo32(ty, getIReg(rs)),
-                                                mkU8(32 - size)), True));
-         }
-         break;
+                     case 0x05:  /* Doubleword Move to Floating Point DMTC1; MIPS64 */
+                        DIP("dmtc1 r%u, f%u", rt, fs);
+                        vassert(mode64);
+                        putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
+                        break;
 
-      case 0x03:  /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
-         msb = get_msb(cins);
-         lsb = get_lsb(cins);
-         size = msb + 1;
-         DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
-         t1 = newTemp(Ity_I64);
-         vassert(lsb >= 0 && lsb < 32);
-         vassert(size > 0 && size <= 32);
-         vassert((lsb + size) > 0 && (lsb + size) <= 63);
+                     case 0x00:  /* MFC1 */
+                        DIP("mfc1 r%u, f%u", rt, fs);
 
-         UChar lsAmt = 63 - (lsb + msb);  /* left shift amount; */
-         UChar rsAmt = 63 - msb;  /* right shift amount; */
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I64);
+                           t1 = newTemp(Ity_I32);
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+                           assign(t1, unop(Iop_64to32, mkexpr(t0)));
+                           putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+                        } else
+                           putIReg(rt, mkWidenFrom32(ty,
+                                                     unop(Iop_ReinterpF32asI32, getFReg(fs)),
+                                                     True));
 
-         assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
-         putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+                        break;
 
-         break;
+                     case 0x01:  /* Doubleword Move from Floating Point DMFC1;
+                           MIPS64 */
+                        DIP("dmfc1 r%u, f%u", rt, fs);
+                        putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
+                        break;
 
-      case 0x20:  /* BSHFL */
-         switch (sa) {
-               case 0x0: /* BITSWAP */
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                     DIP("bitswap r%u, r%u", rd, rt);
-                     if (mode64) {
-                        putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
-                                        mkU8(7), mkU8(8), mkU8(1))));
-                     } else {
-                        putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
-                                        mkU8(8), mkU8(1)));
-                     }
-                  } else {
-                     ILLEGAL_INSTRUCTON;
+                     case 0x06:  /* CTC1 */
+                        DIP("ctc1 r%u, f%u", rt, fs);
+                        t0 = newTemp(Ity_I32);
+                        t1 = newTemp(Ity_I32);
+                        t2 = newTemp(Ity_I32);
+                        t3 = newTemp(Ity_I32);
+                        t4 = newTemp(Ity_I32);
+                        t5 = newTemp(Ity_I32);
+                        t6 = newTemp(Ity_I32);
+                        assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+
+                        if (fs == 25) {  /* FCCR */
+                           assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0x000000FE)), mkU8(24)));
+                           assign(t2, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x01000000)));
+                           assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0x00000001)), mkU8(23)));
+                           assign(t4, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x007FFFFF)));
+                           putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
+                                                         mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
+                                                               mkexpr(t4))));
+                        } else if (fs == 26) {  /* FEXR */
+                           assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
+                           assign(t2, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x0003F000)));
+                           assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
+                           assign(t4, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x0000007C)));
+                           assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
+                           putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+                                                         mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+                                                               mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
+                        } else if (fs == 28) {
+                           assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
+                           assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0x00000002)), mkU8(22)));
+                           assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
+                           assign(t4, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x00000F80)));
+                           assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
+                           assign(t6, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x00000003)));
+                           putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+                                                         mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+                                                               mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
+                                                                     mkexpr(t5), mkexpr(t6))));
+                        } else if (fs == 31) {
+                           putFCSR(mkexpr(t0));
+                        }
+
+                        break;
+
+                     case 0x02:  /* CFC1 */
+                        DIP("cfc1 r%u, f%u", rt, fs);
+                        t0 = newTemp(Ity_I32);
+                        t1 = newTemp(Ity_I32);
+                        t2 = newTemp(Ity_I32);
+                        t3 = newTemp(Ity_I32);
+                        t4 = newTemp(Ity_I32);
+                        t5 = newTemp(Ity_I32);
+                        t6 = newTemp(Ity_I32);
+                        assign(t0, getFCSR());
+
+                        if (fs == 0) {
+                           putIReg(rt, mkWidenFrom32(ty,
+                                                     IRExpr_Get(offsetof(VexGuestMIPS32State,
+                                                                guest_FIR),
+                                                                Ity_I32),
+                                                     False));
+                        } else if (fs == 25) {
+                           assign(t1, mkU32(0x000000FF));
+                           assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0xFE000000)), mkU8(25)));
+                           assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0x00800000)), mkU8(23)));
+                           putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                                               binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                                               mkexpr(t3)), False));
+                        } else if (fs == 26) {
+                           assign(t1, mkU32(0xFFFFF07C));
+                           assign(t2, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x0003F000)));
+                           assign(t3, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x0000007C)));
+                           putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                                               binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                                               mkexpr(t3)), False));
+                        } else if (fs == 28) {
+                           assign(t1, mkU32(0x00000F87));
+                           assign(t2, binop(Iop_And32, mkexpr(t0),
+                                            mkU32(0x00000F83)));
+                           assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                                             mkU32(0x01000000)), mkU8(22)));
+                           putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                                               binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                                               mkexpr(t3)), False));
+                        } else if (fs == 31) {
+                           putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
                   }
-               break;
 
-            case 0x02:  /* WSBH */
-               DIP("wsbh r%u, r%u", rd, rt);
-               t0 = newTemp(Ity_I32);
-               t1 = newTemp(Ity_I32);
-               t2 = newTemp(Ity_I32);
-               t3 = newTemp(Ity_I32);
-               assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
-                                           getIReg(rt)), mkU32(0x00FF0000)),
-                                           mkU8(0x8)));
-               assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
-                                getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
-               assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
-                                getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
-               assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
-                                getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
-               putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
-                                         mkexpr(t0), mkexpr(t1)),
-                                         binop(Iop_Or32, mkexpr(t2),
-                                         mkexpr(t3))), True));
-               break;
+                  break;
 
-            case 0x10:  /* SEB */
-               DIP("seb r%u, r%u", rd, rt);
-               if (mode64)
-                  putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
-               else
-                  putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
-               break;
+               case 0x21:  /* CVT.D */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("cvt.d.s f%u, f%u", fd, fs);
+                        calculateFCSR(fs, 0, CVTDS, True, 1);
 
-            case 0x18:  /* SEH */
-               DIP("seh r%u, r%u", rd, rt);
-               if (mode64)
-                  putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
-               else
-                  putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
-               break;
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I64);
+                           t1 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_F32);
+                           t4 = newTemp(Ity_F32);
+                           /* get lo half of FPR */
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
 
-               case 0x08 ... 0x0b: /* ALIGN */
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                     if (mode64) {
-                        UInt bp = (sa & 0x3) << 3;
-                        if (bp) {
-                           putIReg(rd, unop(Iop_32Sto64,
-                                            binop(Iop_Or32,
-                                                  binop(Iop_Shl32,
-                                                        unop(Iop_64to32,
-                                                             getIReg(rt)),
-                                                        mkU8(bp)),
-                                                  binop(Iop_Shr32,
-                                                        unop(Iop_64to32,
-                                                             getIReg(rs)),
-                                                        mkU8(32 - bp)))));
+                           assign(t1, unop(Iop_64to32, mkexpr(t0)));
+
+                           assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
+
+                           putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
                         } else
-                           putIReg(rd, getIReg(rt));
-                     } else {
-                        UInt bp = (sa & 0x3) << 3;
-                        if (bp) {
-                           putIReg(rd, binop(Iop_Or32,
-                                             binop(Iop_Shl32,
-                                                   getIReg(rt), mkU8(bp)),
-                                             binop(Iop_Shr32,
-                                                   getIReg(rs), mkU8(32 - bp))));
+                           putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
+
+                        break;
+
+                     case 0x14:  /* W */
+                        DIP("cvt.d.w %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CVTDW, True, 1);
+
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I64);
+                           t1 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_F32);
+                           t4 = newTemp(Ity_F32);
+                           /* get lo half of FPR */
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+                           assign(t1, unop(Iop_64to32, mkexpr(t0)));
+                           putDReg(fd, unop(Iop_I32StoF64, mkexpr(t1)));
+                           break;
+                        } else {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                           putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
+                           break;
+                        }
+
+                     case 0x15: {  /* L */
+                        if (fp_mode64) {
+                           DIP("cvt.d.l %u, %u", fd, fs);
+                           calculateFCSR(fs, 0, CVTDL, False, 1);
+                           t0 = newTemp(Ity_I64);
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+                           putFReg(fd, binop(Iop_I64StoF64,
+                                             get_IR_roundingmode(), mkexpr(t0)));
+                           break;
                         } else
-                           putIReg(rd, getIReg(rt));
+                           return -1;
                      }
-                  } else {
-                     ILLEGAL_INSTRUCTON;
+
+                     default:
+                        return -1;
                   }
-                  break;
 
-            default:
-               goto decode_failure;
+                  break;  /* CVT.D */
 
-         }
-         break;  /* BSHFL */
+               case 0x20:  /* CVT.s */
+                  switch (fmt) {
+                     case 0x14:  /* W */
+                        DIP("cvt.s.w %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CVTSW, True, 1);
+
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I64);
+                           t1 = newTemp(Ity_I32);
+                           t3 = newTemp(Ity_F32);
+                           t4 = newTemp(Ity_F32);
+                           /* get lo half of FPR */
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+                           assign(t1, unop(Iop_64to32, mkexpr(t0)));
+                           putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
+                                                                 get_IR_roundingmode(), mkexpr(t1))));
+                        } else {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                           putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
+                                             mkexpr(t0)));
+                        }
 
-      /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
-      case 0xA:  /* LX */
-         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-            if (dis_instr_CVM(cins))
-               break;
-            goto decode_failure;
-         }
-         /* fallthrough */
-      case 0xC:  /* INSV */
-      case 0x38: {  /* EXTR.W */
-         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure_dsp;
-            }
-            break;
-         } else {
-            goto decode_failure_dsp;
-         }
-         break;
-      }
-      case 0x10: {  /* ADDU.QB */
-         switch(sa) {
-            case  0xC:  /* SUBU_S.PH */
-            case  0xD:  /* ADDU_S.PH */
-            case 0x1E: {  /* MULQ_S.PH */
-               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
-                  }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-            default: {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
-                  }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-         }
-         break;
-      }
-      case 0x11: {  /* CMPU.EQ.QB */
-         switch(sa) {
-            case 0x18:  /* CMPGDU.EQ.QB */
-            case 0x19:  /* CMPGDU.LT.QB */
-            case 0x1A:  /* CMPGDU.LE.QB */
-            case 0x0D:  /* PRECR.QB.PH */
-            case 0x1E:  /* PRECR_SRA.PH.W */
-            case 0x1F: {  /* PRECR_SRA_R.PH.W */
-               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
-                  }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-            default: {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("cvt.s.d %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CVTSD, False, 1);
+                        t0 = newTemp(Ity_F32);
+                        assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                         getDReg(fs)));
+                        putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
+                        break;
+
+                     case 0x15:  /* L */
+                        DIP("cvt.s.l %u, %u", fd, fs);
+
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, CVTSL, False, 1);
+                           t0 = newTemp(Ity_I64);
+                           assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+                           putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
+                                                                 get_IR_roundingmode(), mkexpr(t0))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
                   }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-         }
-         break;
-      }
-      case 0x12: {  /* ABSQ_S.PH */
-         switch(sa){
-            case 0x1: {  /* ABSQ_S.QB */
-               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+                  break;  /* CVT.s */
+
+               case 0x24:  /* CVT.w */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("cvt.w.s %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CVTWS, True, 1);
+                        putFReg(fd,
+                                mkWidenFromF32(tyF,
+                                               unop(Iop_ReinterpI32asF32,
+                                                    binop(Iop_F32toI32S,
+                                                          get_IR_roundingmode(),
+                                                          getLoFromF64(tyF,
+                                                                getFReg(fs))))));
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("cvt.w.d %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CVTWD, False, 1);
+                        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:
+                        return -1;
+
                   }
+
                   break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-            default: {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+               case 0x25:  /* CVT.l */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("cvt.l.s %u, %u", fd, fs);
+
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, CVTLS, True, 1);
+                           t0 = newTemp(Ity_I64);
+
+                           assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
+                                            getLoFromF64(tyF, getFReg(fs))));
+
+                           putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
+
+                        break;
+
+                     case 0x11: {  /* D */
+                        DIP("cvt.l.d %u, %u", fd, fs);
+
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, CVTLD, False, 1);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            binop(Iop_F64toI64S,
+                                                  get_IR_roundingmode(),
+                                                  getDReg(fs))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
+
+                        break;
+                     }
+
+                     default:
+                        return -1;
                   }
+
                   break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-         }
-         break;
-      }
-      case 0x13: {  /* SHLL.QB */
-         switch(sa) {
-            case 0x04:  /* SHRA.QB */
-            case 0x05:  /* SHRA_R.QB */
-            case 0x06:  /* SHRAV.QB */
-            case 0x07:  /* SHRAV_R.QB */
-            case 0x19:  /* SHLR.PH */
-            case 0x1B: {  /* SHLRV.PH */
-               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+               case 0x0B:  /* FLOOR.L.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("floor.l.s %u, %u", fd, fs);
+
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, FLOORLS, True, 1);
+                           t0 = newTemp(Ity_I64);
+
+                           assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
+                                            getLoFromF64(tyF, getFReg(fs))));
+
+                           putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
+
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("floor.l.d %u, %u", fd, fs);
+
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, FLOORLD, False, 1);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            binop(Iop_F64toI64S,
+                                                  mkU32(0x01),
+                                                  getDReg(fs))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
                   }
+
                   break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-            default: {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+               case 0x0C:  /* ROUND.W.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("round.w.s f%u, f%u", fd, fs);
+                        calculateFCSR(fs, 0, ROUNDWS, True, 1);
+                        putFReg(fd,
+                                mkWidenFromF32(tyF,
+                                               unop(Iop_ReinterpI32asF32,
+                                                    binop(Iop_F32toI32S,
+                                                          mkU32(0x0),
+                                                          getLoFromF64(tyF,
+                                                                getFReg(fs))))));
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("round.w.d f%u, f%u", fd, fs);
+                        calculateFCSR(fs, 0, ROUNDWD, False, 1);
+
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
+                                            getDReg(fs)));
+                           putFReg(fd, mkWidenFromF32(tyF,
+                                                      unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+                        } else {
+                           t0 = newTemp(Ity_I32);
+
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
+                                            getDReg(fs)));
+
+                           putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
+
                   }
-                  break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-         }
-         break;
-      }
-      case 0x30: {  /* DPAQ.W.PH */
-         switch(sa) {
-            case  0x0:  /* DPA.W.PH */
-            case 0x18:  /* DPAQX_S.W.PH */
-            case 0x1A:  /* DPAQX_SA.W.PH */
-            case  0x8:  /* DPAX.W.PH */
-            case  0x1:  /* DPS.W.PH */
-            case 0x19:  /* DPSQX_S.W.PH */
-            case 0x1B:  /* DPSQX_SA.W.PH */
-            case  0x9:  /* DPSX.W.PH */
-            case  0x2: {  /* MULSA.W.PH */
-               if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+                  break;  /* ROUND.W.fmt */
+
+               case 0x0F:  /* FLOOR.W.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("floor.w.s f%u, f%u", fd, fs);
+                        calculateFCSR(fs, 0, FLOORWS, True, 1);
+                        putFReg(fd,
+                                mkWidenFromF32(tyF,
+                                               unop(Iop_ReinterpI32asF32,
+                                                    binop(Iop_F32toI32S,
+                                                          mkU32(0x1),
+                                                          getLoFromF64(tyF,
+                                                                getFReg(fs))))));
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("floor.w.d f%u, f%u", fd, fs);
+                        calculateFCSR(fs, 0, FLOORWD, False, 1);
+
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
+                                            getDReg(fs)));
+                           putFReg(fd, mkWidenFromF32(tyF,
+                                                      unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+                           break;
+                        } else {
+                           t0 = newTemp(Ity_I32);
+
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
+                                            getDReg(fs)));
+
+                           putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                           break;
+                        }
+
+                     default:
+                        return -1;
+
+                  }
+
+                  break;  /* FLOOR.W.fmt */
+
+               case 0x0D:  /* TRUNC.W */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("trunc.w.s %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, TRUNCWS, True, 1);
+                        putFReg(fd,
+                                mkWidenFromF32(tyF,
+                                               unop(Iop_ReinterpI32asF32,
+                                                    binop(Iop_F32toI32S,
+                                                          mkU32(0x3),
+                                                          getLoFromF64(tyF,
+                                                                getFReg(fs))))));
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("trunc.w.d %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, TRUNCWD, False, 1);
+
+                        if (fp_mode64) {
+                           t0 = newTemp(Ity_I32);
+
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
+                                            getFReg(fs)));
+
+                           putFReg(fd, mkWidenFromF32(tyF,
+                                                      unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+                        } else {
+                           t0 = newTemp(Ity_I32);
+
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
+                                            getDReg(fs)));
+
+                           putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
+
                   }
+
                   break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-            default: {
-               if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                  UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                  if (0 != retVal ) {
-                     goto decode_failure_dsp;
+
+               case 0x0E:  /* CEIL.W.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("ceil.w.s %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CEILWS, True, 1);
+                        putFReg(fd,
+                                mkWidenFromF32(tyF,
+                                               unop(Iop_ReinterpI32asF32,
+                                                    binop(Iop_F32toI32S,
+                                                          mkU32(0x2),
+                                                          getLoFromF64(tyF,
+                                                                getFReg(fs))))));
+                        break;
+
+                     case 0x11:  /* D */
+                        DIP("ceil.w.d %u, %u", fd, fs);
+                        calculateFCSR(fs, 0, CEILWD, False, 1);
+
+                        if (!fp_mode64) {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
+                                            getDReg(fs)));
+                           putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                        } else {
+                           t0 = newTemp(Ity_I32);
+                           assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
+                                            getDReg(fs)));
+                           putFReg(fd, mkWidenFromF32(tyF,
+                                                      unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+                        }
+
+                        break;
+
+                     default:
+                        return -1;
+
                   }
+
                   break;
-               } else {
-                  goto decode_failure_dsp;
-               }
-               break;
-            }
-         }
-         break;
-      }
-      case 0x18:  /* ADDUH.QB/MUL.PH */
-      case 0x31: {  /* APPEND */
-         if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure_dsp;
-            }
-            break;
-         } else {
-            goto decode_failure_dsp;
-         }
-      }
-         case 0x35: { /* PREF r6*/
-            DIP("pref");
-            break;
-         }
-         case 0x36: { /* LL */
-            imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
-            DIP("ll r%u, %u(r%u)", rt, imm, rs);
-            LOAD_STORE_PATTERN;
-            t2 = newTemp(ty);
-            assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
-            putLLaddr(mkexpr(t1));
-            putLLdata(mkexpr(t2));
-            putIReg(rt, mkexpr(t2));
-            break;
-         }
-         case 0x26: { /* SC */
-            imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
-            DIP("sc r%u, %u(r%u)", rt, imm, rs);
-            LOAD_STORE_PATTERN;
 
-            t2 = newTemp(Ity_I1);
-            t3 = newTemp(Ity_I32);
-            assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                             mkexpr(t1), getLLaddr()));
-            assign(t3, mkNarrowTo32(ty, getIReg(rt)));
-            putLLaddr(LLADDR_INVALID);
-            putIReg(rt, getIReg(0));
+               case 0x0A:  /* CEIL.L.fmt */
+                  switch (fmt) {
+                     case 0x10:  /* S */
+                        DIP("ceil.l.s %u, %u", fd, fs);
 
-            mips_next_insn_if(mkexpr(t2));
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, CEILLS, True, 1);
+                           t0 = newTemp(Ity_I64);
 
-            t4 = newTemp(Ity_I32);
-            t5 = newTemp(Ity_I32);
+                           assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
+                                            getLoFromF64(tyF, getFReg(fs))));
 
-            assign(t5, mkNarrowTo32(ty, getLLdata()));
+                           putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
-                 MIPS_IEND, mkexpr(t1),                 /* addr */
-                 NULL, mkexpr(t5),                      /* expected value */
-                 NULL, mkexpr(t3)                       /* new value */)));
+                        break;
 
-            putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
-                             binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
-            break;
-         }
-         case 0x37: { /* LLD */
-            imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
-            DIP("lld r%u, %u(r%u)", rt, imm, rs);
-            LOAD_STORE_PATTERN;
+                     case 0x11:  /* D */
+                        DIP("ceil.l.d %u, %u", fd, fs);
 
-            t2 = newTemp(Ity_I64);
-            assign(t2, load(Ity_I64, mkexpr(t1)));
-            putLLaddr(mkexpr(t1));
-            putLLdata(mkexpr(t2));
-            putIReg(rt, mkexpr(t2));
-            break;
-         }
-         case 0x27: { /* SCD */
-            imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
-            DIP("sdc r%u, %u(r%u)", rt, imm, rs);
-            LOAD_STORE_PATTERN;
+                        if (fp_mode64) {
+                           calculateFCSR(fs, 0, CEILLD, False, 1);
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            binop(Iop_F64toI64S,
+                                                  mkU32(0x2),
+                                                  getDReg(fs))));
+                        } else {
+                           ILLEGAL_INSTRUCTON
+                        }
 
-            t2 = newTemp(Ity_I1);
-            t3 = newTemp(Ity_I64);
-            assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
-            assign(t3, getIReg(rt));
-            putLLaddr(LLADDR_INVALID);
-            putIReg(rt, getIReg(0));
+                        break;
+
+                     default:
+                        return -1;
+
+                  }
+
+                  break;
+
+               case 0x16:  /* RSQRT.fmt */
+                  switch (fmt) {
+                     case 0x10: {  /* S */
+                        DIP("rsqrt.s %u, %u", fd, fs);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+                                                              unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
+                                                              binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
+                                                                    getFReg(fs))))));
+                        break;
+                     }
+
+                     case 0x11: {  /* D */
+                        DIP("rsqrt.d %u, %u", fd, fs);
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, triop(Iop_DivF64, rm,
+                                          unop(Iop_ReinterpI64asF64,
+                                               mkU64(ONE_DOUBLE)),
+                                          binop(Iop_SqrtF64, rm, getDReg(fs))));
+                        break;
+                     }
 
-            mips_next_insn_if(mkexpr(t2));
+                     default:
+                        return -1;
 
-            t4 = newTemp(Ity_I64);
-            t5 = newTemp(Ity_I64);
+                  }
 
-            assign(t5, getLLdata());
+                  break;
 
-            stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
-                 MIPS_IEND, mkexpr(t1),                 /* addr */
-                 NULL, mkexpr(t5),                      /* expected value */
-                 NULL, mkexpr(t3)                       /* new value */)));
+               case 0x18: /* MADDF.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
+                           IRExpr *rm = get_IR_roundingmode();
+                           putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
+                                           getDReg(fd)));
+                           break;
+                        }
 
-            putIReg(rt, unop(Iop_1Uto64,
-                             binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
-            break;
-         }
-      default:
-         goto decode_failure;
+                        case 0x10: {  /* S */
+                           DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
+                           IRExpr *rm = get_IR_roundingmode();
+                           t1 = newTemp(Ity_F32);
+                           assign(t1, qop(Iop_MAddF32, rm,
+                                          getLoFromF64(tyF, getFReg(fs)),
+                                          getLoFromF64(tyF, getFReg(ft)),
+                                          getLoFromF64(tyF, getFReg(fd))));
+                           putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+                           break;
+                        }
 
-   }
-      break;  /* Special3 */
+                        default:
+                           return -1;
+                     }
+                  } else {
+                     ILLEGAL_INSTRUCTON;
+                  }
 
-   case 0x3B: /* PCREL */
-      if (rt == 0x1E) { /* AUIPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("auipc r%u, %u", rs, imm);
-            if (mode64) {
-               putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
-            } else {
-               putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else if (rt == 0x1F) { /* ALUIPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("aluipc r%u, %u", rs, imm);
-            if (mode64) {
-               putIReg(rs, mkU64((~0x0FFFFULL) &
-                                (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
-            } else {
-               putIReg(rs, mkU32((~0x0FFFFULL) &
-                                (guest_PC_curr_instr + (imm << 16))));
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else if ((rt & 0x18) == 0) { /* ADDIUPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
-            if (mode64) {
-               putIReg(rs, mkU64(guest_PC_curr_instr +
-                                 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
-            } else {
-               putIReg(rs, mkU32(guest_PC_curr_instr +
-                                (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else if ((rt & 0x18) == 8) { /* LWPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
-            if (mode64) {
-               t1 = newTemp(Ity_I64);
-               assign(t1, mkU64(guest_PC_curr_instr +
-                                (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
-               putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
-            } else {
-               t1 = newTemp(Ity_I32);
-               assign(t1, mkU32(guest_PC_curr_instr +
-                                (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
-               putIReg(rs, load(Ity_I32, mkexpr(t1)));
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else if ((rt & 0x18) == 16) { /* LWUPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
-            if (mode64) {
-               t1 = newTemp(Ity_I64);
-               assign(t1, mkU64(guest_PC_curr_instr +
-                                (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
-               putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
-            } else {
-               t1 = newTemp(Ity_I32);
-               assign(t1, mkU32(guest_PC_curr_instr +
-                                (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
-               putIReg(rs, load(Ity_I32, mkexpr(t1)));
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else if ((rt & 0x1C) == 0x18) { /* LDPC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
-            t1 = newTemp(Ity_I64);
-            assign(t1, mkU64(guest_PC_curr_instr +
-                             (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
-            putIReg(rs, load(Ity_I64, mkexpr(t1)));
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      } else {
-         goto decode_failure;
-      }
+                  break;
 
-      if (0x3B == function &&
-          (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
-         /*RDHWR*/
-         DIP("rdhwr r%u, r%u", rt, rd);
-         if (rd == 29) {
-            putIReg(rt, getULR());
-         } else
-            goto decode_failure;
-         break;
-      } else {
-         goto decode_failure;
-      }
+               case 0x19: /* MSUBF.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
+                           IRExpr *rm = get_IR_roundingmode();
+                           putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
+                                           getDReg(ft), getDReg(fd)));
+                           break;
+                        }
 
-   case 0x00:  /* Special */
+                        case 0x10: {  /* S */
+                           DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
+                           IRExpr *rm = get_IR_roundingmode();
+                           t1 = newTemp(Ity_F32);
+                           assign(t1, qop(Iop_MSubF32, rm,
+                                          getLoFromF64(tyF, getFReg(fs)),
+                                          getLoFromF64(tyF, getFReg(ft)),
+                                          getLoFromF64(tyF, getFReg(fd))));
+                           putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+                           break;
+                        }
 
-      switch (function) {
-      case 0x1: {
-         UInt mov_cc = get_mov_cc(cins);
-         if (tf == 0) {  /* MOVF */
-            DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
-            t1 = newTemp(Ity_I1);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I1);
+                        default:
+                           return -1;
+                     }
+                  } else {
+                     ILLEGAL_INSTRUCTON;
+                  }
 
-            assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                        mkU32(0x1))
-                                  ));
-            assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
-            putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
-         } else if (tf == 1) {  /* MOVT */
-            DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
-            t1 = newTemp(Ity_I1);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I1);
+                  break;
 
-            assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_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 + mov_cc)),
-                                        mkU32(0x1))
-                                  ));
-            assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
-            putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
-         }
-         break;
-      }
-      case 0x0A: {  /* MOVZ */
-         DIP("movz r%u, r%u, r%u", rd, rs, rt);
-         t1 = newTemp(ty);
-         t2 = newTemp(ty);
-         if (mode64) {
-            assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
-                            getIReg(rt), mkU64(0x0)))));
-            assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
-                            getIReg(rt), mkU64(0x0)))));
-            putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
-                        mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2))));
-         } else {
-            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
-                                              mkU32(0x0))));
-            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
-                                              mkU32(0x0))));
-            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
-                        mkexpr(t1)), binop(Iop_And32, getIReg(rd),
-                        mkexpr(t2))));
-         }
-         break;
-      }
+               case 0x1E: /* MAX.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("max.d f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MAXD, False, 2);
+                           putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
+                           break;
+                        }
 
-      case 0x0B: {  /* MOVN */
-         DIP("movn r%u, r%u, r%u", rd, rs, rt);
-         t1 = newTemp(ty);
-         t2 = newTemp(ty);
-         if (mode64) {
-            assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
-                            getIReg(rt), mkU64(0x0)))));
-            assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
-                            getIReg(rt), mkU64(0x0)))));
-            putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
-                        mkexpr(t2)), binop(Iop_And64, getIReg(rd),
-                                           mkexpr(t1))));
-         } else {
-            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
-                                              mkU32(0x0))));
-            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
-                                              mkU32(0x0))));
-            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
-                        mkexpr(t2)), binop(Iop_And32, getIReg(rd),
-                        mkexpr(t1))));
-         }
-         break;
-      }
+                        case 0x10: {  /* S */
+                           DIP("max.s f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MAXS, True, 2);
+                           putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
+                                                                 getLoFromF64(Ity_F64,
+                                                                       getFReg(fs)),
+                                                                 getLoFromF64(Ity_F64,
+                                                                       getFReg(ft)))));
+                           break;
+                        }
 
-      case 0x18:  {  /* MULT */
-         switch (sa & 0x3) {
-            case 0: {
-               if ((1 <= ac) && ( 3 >= ac)) {
-                  if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                     /* If DSP is present -> DSP ASE MULT */
-                     UInt retVal = disDSPInstr_MIPS_WRK(cins);
-                     if (0 != retVal) {
-                        goto decode_failure_dsp;
+                        default:
+                           return -1;
                      }
-                     break;
                   } else {
-                      goto decode_failure_dsp;
-                  }
-               } else {
-                  DIP("mult r%u, r%u", rs, rt);
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                      !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
                      ILLEGAL_INSTRUCTON;
                   }
-                  t2 = newTemp(Ity_I64);
-
-                  assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
-                                                mkNarrowTo32(ty, getIReg(rt))));
 
-                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
-                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
                   break;
-               }
-            }
-            case 2: { /* MUL R6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("mul r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Sto64,
-                                      unop(Iop_64to32,
-                                           binop(Iop_MullS32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
-                  } else {
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_MullS32,
-                                            getIReg(rs), getIReg(rt))));
-                  }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            }
 
-            case 3: {  /* MUH R6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("muh r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Sto64,
-                                      unop(Iop_64HIto32,
-                                           binop(Iop_MullS32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
+               case 0x1C: /* MIN.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("min.d f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MIND, False, 2);
+                           putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
+                           break;
+                        }
+
+                        case 0x10: {  /* S */
+                           DIP("min.s f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MINS, True, 2);
+                           putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
+                                                                 getLoFromF64(Ity_F64,
+                                                                       getFReg(fs)),
+                                                                 getLoFromF64(Ity_F64,
+                                                                       getFReg(ft)))));
+                           break;
+                        }
+
+                        default:
+                           return -1;
+                     }
                   } else {
-                     putIReg(rd, unop(Iop_64HIto32,
-                                      binop(Iop_MullS32,
-                                            getIReg(rs), getIReg(rt))));
+                     ILLEGAL_INSTRUCTON;
                   }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            }
-         }
-         break;
-      }
 
-      case 0x19:  {  /* MULTU */
-         switch (sa & 0x3) {
-            case 0: {
-               if ((1 <= ac) && ( 3 >= ac)) {
-                  if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-                     /* If DSP is present -> DSP ASE MULTU */
-                     UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-                     if (0 != retVal) {
-                        goto decode_failure_dsp;
+                  break;
+
+               case 0x1F: /* MAXA.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MAXAD, False, 2);
+                           t1 = newTemp(Ity_F64);
+                           t2 = newTemp(Ity_F64);
+                           t3 = newTemp(Ity_F64);
+                           t4 = newTemp(Ity_I1);
+                           assign(t1, unop(Iop_AbsF64, getFReg(fs)));
+                           assign(t2, unop(Iop_AbsF64, getFReg(ft)));
+                           assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
+                           assign(t4, binop(Iop_CmpEQ32,
+                                            binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
+                                            mkU32(0x40)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t4),
+                                                  getFReg(fs), getFReg(ft)));
+                           break;
+                        }
+
+                        case 0x10: {  /* S */
+                           DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MAXAS, True, 2);
+                           t1 = newTemp(Ity_F32);
+                           t2 = newTemp(Ity_F32);
+                           t3 = newTemp(Ity_F32);
+                           t4 = newTemp(Ity_I1);
+                           assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+                                           getFReg(fs))));
+                           assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+                                           getFReg(ft))));
+                           assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
+                           assign(t4, binop(Iop_CmpEQ32,
+                                            binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
+                                            mkU32(0x40)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t4),
+                                                  getFReg(fs), getFReg(ft)));
+                           break;
+                        }
+
+                        default:
+                           return -1;
                      }
-                     break;
+
                   } else {
-                     goto decode_failure_dsp;
-                  }
-               } else {
-                  DIP("multu r%u, r%u", rs, rt);
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                      !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
                      ILLEGAL_INSTRUCTON;
                   }
-                  t2 = newTemp(Ity_I64);
 
-                  assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
-                                                mkNarrowTo32(ty, getIReg(rt))));
+                  break;
+
+               case 0x1D: /* MINA.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MINAD, False, 2);
+                           t1 = newTemp(Ity_F64);
+                           t2 = newTemp(Ity_F64);
+                           t3 = newTemp(Ity_F64);
+                           t4 = newTemp(Ity_I1);
+                           assign(t1, unop(Iop_AbsF64, getFReg(fs)));
+                           assign(t2, unop(Iop_AbsF64, getFReg(ft)));
+                           assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
+                           assign(t4, binop(Iop_CmpEQ32,
+                                            binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
+                                            mkU32(0x40)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t4),
+                                                  getFReg(fs), getFReg(ft)));
+                           break;
+                        }
+
+                        case 0x10: {  /* S */
+                           DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
+                           calculateFCSR(fs, ft, MINAS, True, 2);
+                           t1 = newTemp(Ity_F32);
+                           t2 = newTemp(Ity_F32);
+                           t3 = newTemp(Ity_F32);
+                           t4 = newTemp(Ity_I1);
+                           assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+                                           getFReg(fs))));
+                           assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+                                           getFReg(ft))));
+                           assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
+                           assign(t4, binop(Iop_CmpEQ32,
+                                            binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
+                                            mkU32(0x40)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t4),
+                                                  getFReg(fs), getFReg(ft)));
+                           break;
+                        }
+
+                        default:
+                           return -1;
+                     }
+                  }
 
-                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
-                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
                   break;
-               }
-            }
-            case 2: {  /* MULU R6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("mulu r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Uto64,
-                                      unop(Iop_64to32,
-                                           binop(Iop_MullU32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
-                  } else {
-                     putIReg(rd, unop(Iop_64to32,
-                                      binop(Iop_MullU32,
-                                            getIReg(rs), getIReg(rt))));
+
+               case 0x1A: /* RINT.fmt */
+                  if (ft == 0) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("rint.d f%u, f%u", fd, fs);
+                           calculateFCSR(fs, 0, RINTS, True, 1);
+                           IRExpr *rm = get_IR_roundingmode();
+                           putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
+                           break;
+                        }
+
+                        case 0x10: {  /* S */
+                           DIP("rint.s f%u, f%u", fd, fs);
+                           calculateFCSR(fs, 0, RINTD, True, 1);
+                           IRExpr *rm = get_IR_roundingmode();
+                           putFReg(fd,
+                                   mkWidenFromF32(tyF,
+                                                  binop(Iop_RoundF32toInt, rm,
+                                                        getLoFromF64(tyF,
+                                                              getFReg(fs)))));
+                           break;
+                        }
+
+                        default:
+                           return -1;
+                     }
+
                   }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            }
-            case 3: {  /* MUHU R6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("muhu r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Uto64,
-                                      unop(Iop_64HIto32,
-                                           binop(Iop_MullU32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
-                  } else {
-                     putIReg(rd, unop(Iop_64HIto32,
-                                      binop(Iop_MullU32,
-                                            getIReg(rs), getIReg(rt))));
+
+                  break;
+
+               case 0x10: /* SEL.fmt */
+                  switch (fmt) {
+                     case 0x11: {  /* D */
+                        if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                           DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
+                           t1 = newTemp(Ity_I1);
+
+                           if (mode64) {
+                              assign(t1, binop(Iop_CmpNE64,
+                                               binop(Iop_And64,
+                                                     unop(Iop_ReinterpF64asI64,
+                                                          getDReg(fd)),
+                                                     mkU64(1)),
+                                               mkU64(0)));
+                           } else {
+                              assign(t1, binop(Iop_CmpNE32,
+                                               binop(Iop_And32,
+                                                     unop(Iop_64to32,
+                                                          unop(Iop_ReinterpF64asI64,
+                                                               getDReg(fd))),
+                                                     mkU32(1)),
+                                               mkU32(0)));
+                           }
+
+                           putDReg(fd, IRExpr_ITE(mkexpr(t1),
+                                                  getDReg(ft), getDReg(fs)));
+                           break;
+                        } else {
+                           ILLEGAL_INSTRUCTON;
+                           break;
+                        }
+
+                     }
+
+                     case 0x10: {  /* S */
+                        DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
+                        t1 = newTemp(Ity_I1);
+                        assign(t1, binop(Iop_CmpNE32,
+                                         binop(Iop_And32,
+                                               unop(Iop_ReinterpF32asI32,
+                                                    getLoFromF64(tyF, getFReg(fd))),
+                                               mkU32(1)),
+                                         mkU32(0)));
+                        putFReg(fd, IRExpr_ITE( mkexpr(t1),
+                                                getFReg(ft), getFReg(fs)));
+                        break;
+                     }
+
+                     default:
+                        return -1;
                   }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            }
-         }
-      }
-      break;
 
-      case 0x20: {  /* ADD */
-         DIP("add r%u, r%u, r%u", rd, rs, rt);
-         IRTemp tmpRs32 = newTemp(Ity_I32);
-         IRTemp tmpRt32 = newTemp(Ity_I32);
+                  break;
 
-         assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
-         assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+               case 0x14: /* SELEQZ.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) { /* SELEQZ.df */
+                        case 0x11: {  /* D */
+                           DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
+                           t1 = newTemp(Ity_I1);
+
+                           if (mode64) {
+                              assign(t1, binop(Iop_CmpNE64,
+                                               binop(Iop_And64,
+                                                     unop(Iop_ReinterpF64asI64,
+                                                          getDReg(ft)),
+                                                     mkU64(1)),
+                                               mkU64(0)));
+                           } else {
+                              assign(t1, binop(Iop_CmpNE32,
+                                               binop(Iop_And32,
+                                                     unop(Iop_64to32,
+                                                          unop(Iop_ReinterpF64asI64,
+                                                               getDReg(ft))),
+                                                     mkU32(1)),
+                                               mkU32(0)));
+                           }
 
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         t2 = newTemp(Ity_I32);
-         t3 = newTemp(Ity_I32);
-         t4 = newTemp(Ity_I32);
-         /* dst = src0 + src1
-            if (sign(src0 ) != sign(src1 ))
-            goto no overflow;
-            if (sign(dst) == sign(src0 ))
-            goto no overflow;
-            we have overflow! */
+                           putDReg(fd, IRExpr_ITE( mkexpr(t1),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(), mkU64(0)),
+                                                   getDReg(fs)));
+                           break;
+                        }
 
-         assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-         assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-         assign(t2, unop(Iop_1Uto32,
-                         binop(Iop_CmpEQ32,
-                               binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
-                               mkU32(0x80000000))));
+                        case 0x10: {  /* S */
+                           DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
+                           t1 = newTemp(Ity_I1);
+                           assign(t1, binop(Iop_CmpNE32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(ft))),
+                                                  mkU32(1)),
+                                            mkU32(0)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t1),
+                                                  mkWidenFromF32(tyF,
+                                                                 binop(Iop_I32StoF32,
+                                                                       get_IR_roundingmode(),
+                                                                       mkU32(0))),
+                                                  getFReg(fs)));
+                           break;
+                        }
 
-         assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
-         assign(t4, unop(Iop_1Uto32,
-                         binop(Iop_CmpNE32,
-                               binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
-                               mkU32(0x80000000))));
+                        default:
+                           return -1;
+                     }
+                  } else {
+                     ILLEGAL_INSTRUCTON;
+                  }
 
-         stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
-                                binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
-                                mkU32(0)),
-                          Ijk_SigFPE_IntOvf,
-                          mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
-                                   IRConst_U32(guest_PC_curr_instr + 4),
-                          OFFB_PC));
+                  break;
 
-         putIReg(rd,  mkWidenFrom32(ty, mkexpr(t0), True));
-         break;
-      }
+               case 0x17: /* SELNEZ.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
+                           t1 = newTemp(Ity_I1);
+
+                           if (mode64) {
+                              assign(t1, binop(Iop_CmpNE64,
+                                               binop(Iop_And64,
+                                                     unop(Iop_ReinterpF64asI64,
+                                                          getDReg(ft)),
+                                                     mkU64(1)),
+                                               mkU64(0)));
+                           } else {
+                              assign(t1, binop(Iop_CmpNE32,
+                                               binop(Iop_And32,
+                                                     unop(Iop_64to32,
+                                                          unop(Iop_ReinterpF64asI64,
+                                                               getDReg(ft))),
+                                                     mkU32(1)),
+                                               mkU32(0)));
+                           }
 
-      case 0x1A:  /* DIV */
-         switch (sa & 0x3) {
-            case 0:
-               DIP("div r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
-               }
-               if (mode64) {
-                  t2 = newTemp(Ity_I64);
+                           putDReg(fd, IRExpr_ITE( mkexpr(t1),
+                                                   getDReg(fs),
+                                                   binop(Iop_I64StoF64,
+                                                         get_IR_roundingmode(),
+                                                         mkU64(0))));
+                           break;
+                        }
 
-                  assign(t2, binop(Iop_DivModS32to32,
-                                   mkNarrowTo32(ty, getIReg(rs)),
-                                   mkNarrowTo32(ty, getIReg(rt))));
+                        case 0x10: {  /* S */
+                           DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
+                           t1 = newTemp(Ity_I1);
+                           assign(t1, binop(Iop_CmpNE32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(ft))),
+                                                  mkU32(1)),
+                                            mkU32(0)));
+                           putFReg(fd, IRExpr_ITE(mkexpr(t1),
+                                                  getFReg(fs),
+                                                  mkWidenFromF32(tyF,
+                                                                 binop(Iop_I32StoF32,
+                                                                       get_IR_roundingmode(),
+                                                                       mkU32(0)))));
+                           break;
+                        }
 
-                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
-                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
-               } else {
-                  t1 = newTemp(Ity_I64);
+                        default:
+                           return -1;
 
-                  assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
+                     }
 
-                  putHI(unop(Iop_64HIto32, mkexpr(t1)));
-                  putLO(unop(Iop_64to32, mkexpr(t1)));
-               }
-               break;
-            case 2:
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("div r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Sto64,
-                                      binop(Iop_DivS32,
-                                            unop(Iop_64to32, getIReg(rs)),
-                                            unop(Iop_64to32, getIReg(rt)))));
-                  } else
-                     putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            case 3:
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("mod r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Sto64,
-                                      unop(Iop_64HIto32,
-                                           binop(Iop_DivModS32to32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
                   } else {
-                     t1 = newTemp(Ity_I64);
-
-                     assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
-                     putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+                     ILLEGAL_INSTRUCTON;
                   }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-         }
-         break;
 
-      case 0x1B:  /* DIVU */
-         switch (sa & 0x3) {
-            case 0:
-               DIP("divu r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
-               }
-               if (mode64) {
-                  t1 = newTemp(Ity_I64);
+                  break;
 
-                  assign(t1, binop(Iop_DivModU32to32,
-                                   mkNarrowTo32(ty, getIReg(rs)),
-                                   mkNarrowTo32(ty, getIReg(rt))));
+               case 0x1B: /* CLASS.fmt */
+                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+                     t0 = newTemp(Ity_I1); // exp zero
+                     t1 = newTemp(Ity_I1); // exp max
+                     t2 = newTemp(Ity_I1); // sign
+                     t3 = newTemp(Ity_I1); // first
+                     t4 = newTemp(Ity_I1); // val not zero
+                     t5 = newTemp(Ity_I32);
+
+                     switch (fmt) {
+                        case 0x11: {  /* D */
+                           DIP("class.d f%u, f%u", fd, fs);
+                           assign(t0, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                       unop(Iop_ReinterpF64asI64,
+                                                            getDReg(fs))),
+                                                  mkU32(0x7ff00000)),
+                                            mkU32(0)));
+                           assign(t1, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                       unop(Iop_ReinterpF64asI64,
+                                                            getDReg(fs))),
+                                                  mkU32(0x7ff00000)),
+                                            mkU32(0x7ff00000)));
+                           assign(t2, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                       unop(Iop_ReinterpF64asI64,
+                                                            getDReg(fs))),
+                                                  mkU32(0x80000000)),
+                                            mkU32(0x80000000)));
+                           assign(t3, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                       unop(Iop_ReinterpF64asI64,
+                                                            getDReg(fs))),
+                                                  mkU32(0x00080000)),
+                                            mkU32(0x00080000)));
+
+                           if (mode64) assign(t4, binop(Iop_CmpNE64,
+                                                           binop(Iop_And64,
+                                                                 unop(Iop_ReinterpF64asI64,
+                                                                      getDReg(fs)),
+                                                                 mkU64(0x000fffffffffffffULL)),
+                                                           mkU64(0)));
+                           else assign(t4, binop(Iop_CmpNE32,
+                                                    binop(Iop_Or32,
+                                                          binop(Iop_And32,
+                                                                unop(Iop_64HIto32,
+                                                                     unop(Iop_ReinterpF64asI64,
+                                                                           getDReg(fs))),
+                                                                mkU32(0x000fffff)),
+                                                          unop(Iop_64to32,
+                                                               unop(Iop_ReinterpF64asI64,
+                                                                    getDReg(fs)))),
+                                                    mkU32(0)));
+
+                           assign(t5, binop(Iop_Shl32,
+                                            IRExpr_ITE(mkexpr(t1),
+                                                       IRExpr_ITE(mkexpr(t4),
+                                                                  mkU32(0), mkU32(1)),
+                                                       IRExpr_ITE(mkexpr(t0),
+                                                                  IRExpr_ITE(mkexpr(t4),
+                                                                        mkU32(0x4),
+                                                                        mkU32(0x8)),
+                                                                  mkU32(2))),
+                                            IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            unop(Iop_32Uto64,
+                                                 IRExpr_ITE(binop(Iop_CmpNE32,
+                                                                  mkexpr(t5), mkU32(0)),
+                                                            mkexpr(t5),
+                                                            IRExpr_ITE(mkexpr(t3),
+                                                                  mkU32(2),
+                                                                  mkU32(1))))));
+                           break;
+                        }
 
-                  putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
-                  putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
-               } else {
-                  t1 = newTemp(Ity_I64);
+                        case 0x10: {  /* S */
+                           DIP("class.s f%u, f%u", fd, fs);
+                           assign(t0, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(fs))),
+                                                  mkU32(0x7f800000)),
+                                            mkU32(0)));
+                           assign(t1, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(fs))),
+                                                  mkU32(0x7f800000)),
+                                            mkU32(0x7f800000)));
+                           assign(t2, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(fs))),
+                                                  mkU32(0x80000000)),
+                                            mkU32(0x80000000)));
+                           assign(t3, binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(fs))),
+                                                  mkU32(0x00400000)),
+                                            mkU32(0x00400000)));
+                           assign(t4, binop(Iop_CmpNE32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_ReinterpF32asI32,
+                                                       getLoFromF64(tyF, getFReg(fs))),
+                                                  mkU32(0x007fffff)),
+                                            mkU32(0)));
+                           assign(t5, binop(Iop_Shl32,
+                                            IRExpr_ITE(mkexpr(t1),
+                                                       IRExpr_ITE(mkexpr(t4),
+                                                                  mkU32(0), mkU32(1)),
+                                                       IRExpr_ITE(mkexpr(t0),
+                                                                  IRExpr_ITE(mkexpr(t4),
+                                                                        mkU32(0x4),
+                                                                        mkU32(0x8)), //zero or subnorm
+                                                                  mkU32(2))),
+                                            IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
+                           putDReg(fd, unop(Iop_ReinterpI64asF64,
+                                            unop(Iop_32Uto64,
+                                                 IRExpr_ITE(binop(Iop_CmpNE32,
+                                                                  mkexpr(t5), mkU32(0)),
+                                                            mkexpr(t5),
+                                                            IRExpr_ITE(mkexpr(t3),
+                                                                  mkU32(2),
+                                                                  mkU32(1))))));
+                           break;
+                        }
 
-                  assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
-                  putHI(unop(Iop_64HIto32, mkexpr(t1)));
-                  putLO(unop(Iop_64to32, mkexpr(t1)));
-               }
-               break;
-            case 2:
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("divu r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Sto64,
-                                      binop(Iop_DivU32,
-                                            unop(Iop_64to32, getIReg(rs)),
-                                            unop(Iop_64to32, getIReg(rt)))));
+                        default:
+                           return -1;
+                     }
                   } else {
-                     putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
+                     ILLEGAL_INSTRUCTON;
                   }
+
                   break;
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-            case 3:
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("modu r%u, r%u, r%u", rs, rt, rd);
-                  if (mode64) {
-                     putIReg(rd, unop(Iop_32Uto64,
-                                      unop(Iop_64HIto32,
-                                           binop(Iop_DivModU32to32,
-                                                 unop(Iop_64to32, getIReg(rs)),
-                                                 unop(Iop_64to32, getIReg(rt))))));
-                  } else {
-                     t1 = newTemp(Ity_I64);
 
-                     assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
-                     putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
-                  }
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
-        }
-        break;
+               default:
+                  if (dis_instr_CCondFmt(cins))
+                     break;
 
-      case 0x1C:  /* Doubleword Multiply - DMULT; MIPS64 */
-         switch (sa) {
-            case 0:
-               DIP("dmult r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
-               }
-               t0 = newTemp(Ity_I128);
+                  return -1;
 
-               assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
+            }
 
-               putHI(unop(Iop_128HIto64, mkexpr(t0)));
-               putLO(unop(Iop_128to64, mkexpr(t0)));
-               break;
-            case 2: /* DMUL */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmul r%u, r%u, r%u", rd, rs, rt);
-                  putIReg(rd, unop(Iop_128to64,
-                                   binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               /* Value for function in documentation is 111000 */
-               break;
-            case 3: /* DMUH */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
-                  putIReg(rd, unop(Iop_128HIto64,
-                                   binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
-               break;
          }
-         break;
+      }
+      break;  /* COP1 */
 
-      case 0x1D:  /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
-         switch (sa) {
-            case 0:
-               DIP("dmultu r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
-               }
-               t0 = newTemp(Ity_I128);
+      case 0x03:  /* COP1X */
+         switch (function) {
+            case 0x0: {  /* LWXC1 */
+               /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
+               DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
+               t2 = newTemp(ty);
+               assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                                getIReg(rt)));
+
+               if (fp_mode64) {
+                  t0 = newTemp(Ity_I64);
+                  t1 = newTemp(Ity_I32);
+                  t3 = newTemp(Ity_F32);
+                  t4 = newTemp(Ity_I64);
+                  assign(t3, load(Ity_F32, mkexpr(t2)));
 
-               assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
+                  assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+                                                         mkexpr(t3)), True));
 
-               putHI(unop(Iop_128HIto64, mkexpr(t0)));
-               putLO(unop(Iop_128to64, mkexpr(t0)));
-               break;
-            case 2: /* DMULU */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
-                  putIReg(rd, unop(Iop_128to64,
-                                   binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+                  putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  putFReg(fd, load(Ity_F32, mkexpr(t2)));
                }
+
                break;
-            case 3: /* DMUHU */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
-                  putIReg(rd, unop(Iop_128HIto64,
-                                   binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+            }
+
+            case 0x1: {  /* LDXC1 */
+               /* Load Doubleword  Indexed to Floating Point
+                  LDXC1 (MIPS32r2 and MIPS64) */
+               DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
+               t0 = newTemp(ty);
+               assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                                getIReg(rt)));
+               putDReg(fd, load(Ity_F64, mkexpr(t0)));
+               break;
+            }
+
+            case 0x5:  /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
+                     MIPS32r2 and MIPS64 */
+               DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
+
+               if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
+                     && fp_mode64) {
+                  t0 = newTemp(ty);
+                  t1 = newTemp(ty);
+                  assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
+                                   getIReg(rs), getIReg(rt)));
+                  assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
+                                   mkexpr(t0),
+                                   mode64 ? mkU64(0xfffffffffffffff8ULL)
+                                   : mkU32(0xfffffff8ULL)));
+                  putFReg(fd, load(Ity_F64, mkexpr(t1)));
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  ILLEGAL_INSTRUCTON
                }
+
                break;
-         }
-         break;
 
-      case 0x1E:  /* Doubleword Divide DDIV; MIPS64 */
-         switch (sa) {
-            case 0:
-               DIP("ddiv r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
+            case 0x8: {  /* Store Word Indexed from Floating Point - SWXC1 */
+               DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
+               t0 = newTemp(ty);
+               assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                                getIReg(rt)));
+
+               if (fp_mode64) {
+                  store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
+               } else {
+                  store(mkexpr(t0), getFReg(fs));
                }
-               t1 = newTemp(Ity_I128);
 
-               assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
+               break;
+            }
 
-               putHI(unop(Iop_128HIto64, mkexpr(t1)));
-               putLO(unop(Iop_128to64, mkexpr(t1)));
+            case 0x9: {  /* Store Doubleword Indexed from Floating Point - SDXC1 */
+               DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
+               t0 = newTemp(ty);
+               assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+                                getIReg(rt)));
+               store(mkexpr(t0), getDReg(fs));
                break;
-            case 2: /* DDIV r6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
-                  putIReg(rd, unop(Iop_128to64,
-                                   binop(Iop_DivModS64to64,
-                                         getIReg(rs), getIReg(rt))));
+            }
+
+            case 0xD:  /* Store Doubleword Indexed Unaligned from Floating Point -
+                     SUXC1; MIPS64 MIPS32r2 */
+               DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
+
+               if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
+                     && fp_mode64) {
+                  t0 = newTemp(ty);
+                  t1 = newTemp(ty);
+                  assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
+                                   getIReg(rs), getIReg(rt)));
+                  assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
+                                   mkexpr(t0),
+                                   mode64 ? mkU64(0xfffffffffffffff8ULL)
+                                   : mkU32(0xfffffff8ULL)));
+                  store(mkexpr(t1), getFReg(fs));
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  ILLEGAL_INSTRUCTON
                }
+
                break;
-            case 3: /* DMOD r6 */
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmod r%u, r%u, r%u", rs, rt, rd);
-                  t2 = newTemp(Ity_I128);
-                  assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
-                  putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
-               } else {
-                  ILLEGAL_INSTRUCTON;
-               }
+
+            case 0x0F: {
+               DIP("prefx");
                break;
+            }
+
+            case 0x20:  {  /* MADD.S */
+               DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F32);
+               assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
+                                triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                                      getLoFromF64(tyF, getFReg(ft)))));
+               putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+               break;  /* MADD.S */
+            }
+
+            case 0x21: {  /* MADD.D */
+               DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
+                                 triop(Iop_MulF64, rm, getDReg(fs),
+                                       getDReg(ft))));
+               break;  /* MADD.D */
+            }
+
+            case 0x28: {  /* MSUB.S */
+               DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F32);
+               assign(t1, triop(Iop_SubF32, rm,
+                                triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                                      getLoFromF64(tyF, getFReg(ft))),
+                                getLoFromF64(tyF, getFReg(fmt))));
+               putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+               break;  /* MSUB.S */
+            }
+
+            case 0x29: {  /* MSUB.D */
+               DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
+                                                       getDReg(ft)), getDReg(fmt)));
+               break;  /* MSUB.D */
+            }
+
+            case 0x30: {  /* NMADD.S */
+               DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F32);
+               assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
+                                triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                                      getLoFromF64(tyF, getFReg(ft)))));
+               putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
+               break;  /* NMADD.S */
+            }
+
+            case 0x31: {  /* NMADD.D */
+               DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F64);
+               assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
+                                triop(Iop_MulF64, rm, getDReg(fs),
+                                      getDReg(ft))));
+               putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
+               break;  /* NMADD.D */
+            }
+
+            case 0x38: {  /* NMSUBB.S */
+               DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F32);
+               assign(t1, triop(Iop_SubF32, rm,
+                                triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                                      getLoFromF64(tyF, getFReg(ft))),
+                                getLoFromF64(tyF, getFReg(fmt))));
+               putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
+               break;  /* NMSUBB.S */
+            }
+
+            case 0x39: {  /* NMSUBB.D */
+               DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+               IRExpr *rm = get_IR_roundingmode();
+               t1 = newTemp(Ity_F64);
+               assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
+                                                      getDReg(ft)), getDReg(fmt)));
+               putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
+               break;  /* NMSUBB.D */
+            }
+
+            default:
+               return -1;
          }
+
          break;
 
-      case 0x1F:  /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
-         switch (sa) {
-            case 0:
-               DIP("ddivu r%u, r%u", rs, rt);
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                   !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                  ILLEGAL_INSTRUCTON;
-               }
-               t1 = newTemp(Ity_I128);
+      case 0x04:  /* BEQL */
+         DIP("beql r%u, r%u, %u", rs, rt, imm);
+         *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                                          getIReg(rs), getIReg(rt)), imm);
+         break;
 
-               assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
+      case 0x05:  /* BNEL */
+         DIP("bnel r%u, r%u, %u", rs, rt, imm);
+         *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
+                                          getIReg(rs), getIReg(rt)), imm);
+         break;
 
-               putHI(unop(Iop_128HIto64, mkexpr(t1)));
-               putLO(unop(Iop_128to64, mkexpr(t1)));
-               break;
-            case 2:
-               if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
-                  putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
-                                                      getIReg(rs), getIReg(rt))));
+      case 0x06:  /* 0x16 ??? BLEZL, BLEZC, BGEZC, BGEC */
+         if (rt == 0) { /* BLEZL */
+            DIP("blezl r%u, %u", rs, imm);
+            *lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
+                                            Iop_CmpLE32S, getIReg(rs), mode64 ?
+                                            mkU64(0x0) : mkU32(0x0)))), imm);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) { /* BLEZC */
+               DIP("blezc r%u, %u", rt, imm);
+
+               if (mode64) {
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
+                                     imm, dres);
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
+                                     imm, dres);
                }
-               break;
-            case 3:
-              if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-                  DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
-                  putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
-                                                        getIReg(rs), getIReg(rt))));
+            } else if (rt == rs) { /* BGEZC */
+               DIP("bgezc r%u, %u", rt, imm);
+
+               if (mode64) {
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
+                                     imm, dres);
                } else {
-                  ILLEGAL_INSTRUCTON;
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
+                                     imm, dres);
                }
-               break;
-         }
-         break;
+            } else { /* BGEC */
+               DIP("bgec r%u, r%u, %u", rs, rt, imm);
 
-      case 0x10: {  /* MFHI, CLZ R6 */
-         if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
-            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-               DIP("clz r%u, r%u", rd, rs);
                if (mode64) {
-                  IRTemp tmpClz32 = newTemp(Ity_I32);
-                  IRTemp tmpRs32 = newTemp(Ity_I32);
-
-                  assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
-                  assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
-                  putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
+                                     imm, dres);
                } else {
-                  t1 = newTemp(Ity_I1);
-                  assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
-                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                         mkU32(0x00000020),
-                                         unop(Iop_Clz32, getIReg(rs))));
+                  dis_branch_compact(False,
+                                     binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
+                                     imm, dres);
                }
-            } else {
-               ILLEGAL_INSTRUCTON;
-            }
-            break;
-         } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-            /* If DSP is present -> DSP ASE MFHI */
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure;
             }
-            break;
          } else {
-            DIP("mfhi r%u", rd);
-            putIReg(rd, getHI());
-            break;
+            ILLEGAL_INSTRUCTON
          }
-      }
 
-      case 0x11:  {  /* MTHI, CLO R6 */
-         if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
-            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-               DIP("clo r%u, r%u", rd, rs);
+         break;
+
+      case 0x07:  /* BGTZL, BGTZC, BLTZC, BLTC */
+         if (rt == 0) { /* BGTZL */
+            DIP("bgtzl r%u, %u", rs, imm);
+
+            if (mode64)
+               *lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
+                                                mkU64(0x00)), imm);
+            else
+               *lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
+                                                mkU32(0x00)), imm);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) { /* BGTZC */
+               DIP("bgtzc r%u, %u", rt, imm);
+
                if (mode64) {
-                  IRTemp tmpClo32 = newTemp(Ity_I32);
-                  IRTemp tmpRs32 = newTemp(Ity_I32);
-                  assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE64S,
+                                                getIReg(rt), mkU64(0x0))),
+                                     imm, dres);
+               } else {
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE32S,
+                                                getIReg(rt), mkU32(0x0))),
+                                     imm, dres);
+               }
+            } else if (rs == rt) { /* BLTZC */
+               DIP("bltzc r%u, %u", rt, imm);
 
-                  t1 = newTemp(Ity_I1);
-                  assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
-                  assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
-                            mkU32(0x00000020),
-                            unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
+               if (mode64) {
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE64S,
+                                                mkU64(0x0), getIReg(rt))),
+                                     imm, dres);
+               } else {
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE32S,
+                                                mkU32(0x0), getIReg(rt))),
+                                     imm, dres);
+               }
+            } else { /* BLTC */
+               DIP("bltc r%u, r%u, %u", rs, rt, imm);
 
-                  putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
-                  break;
+               if (mode64) {
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE64S,
+                                                getIReg(rt), getIReg(rs))),
+                                     imm, dres);
                } else {
-                  t1 = newTemp(Ity_I1);
-                  assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
-                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                         mkU32(0x00000020),
-                                         unop(Iop_Clz32,
-                                              unop(Iop_Not32, getIReg(rs)))));
+                  dis_branch_compact(False,
+                                     unop(Iop_Not1,
+                                          binop(Iop_CmpLE32S,
+                                                getIReg(rt), getIReg(rs))),
+                                     imm, dres);
                }
-            } else {
-               ILLEGAL_INSTRUCTON;
-            }
-            break;
-         } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-            /* If DSP is present -> DSP ASE MTHI */
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure;
             }
-            break;
          } else {
-            DIP("mthi r%u", rs);
-            putHI(getIReg(rs));
-            break;
+            ILLEGAL_INSTRUCTON
          }
+
+         break;
+
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
+
+      case 0x08: {  /* Doubleword Add Immidiate - DADDI; MIPS64 */
+         DIP("daddi r%u, r%u, %u", rt, rs, imm);
+         IRTemp tmpRs64 = newTemp(Ity_I64);
+         assign(tmpRs64, getIReg(rs));
+
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I64);
+         /* dst = src0 + sign(imm)
+            if(sign(src0 ) != sign(imm ))
+            goto no overflow;
+            if(sign(dst) == sign(src0 ))
+            goto no overflow;
+            we have overflow! */
+
+         assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
+                          mkU64(extend_s_16to64(imm))));
+         assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
+                          mkU64(extend_s_16to64(imm))));
+         assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
+                                           mkexpr(t1), mkU64(0x8000000000000000ULL)),
+                                           mkU64(0x8000000000000000ULL))));
+
+         assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+         assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
+                                           mkexpr(t3), mkU64(0x8000000000000000ULL)),
+                                           mkU64(0x8000000000000000ULL))));
+
+         stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
+                                mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
+                          IRConst_U64(guest_PC_curr_instr + 4),
+                          OFFB_PC));
+
+         putIReg(rt,  mkexpr(t0));
+         break;
       }
 
-      case 0x12:  {  /* MFLO */
-         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-            /* If DSP is present -> DSP ASE MFLO */
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure;
-            }
-            break;
-         } else {
-            switch (sa) {
-               case 0:
-                  DIP("mflo r%u", rd);
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                      !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                     ILLEGAL_INSTRUCTON;
-                  }
-                  putIReg(rd, getLO());
-                  break;
-               case 1:
-                  DIP("dclz r%u, r%u", rd, rs);
-                  t1 = newTemp(Ity_I1);
-                  assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
-                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                         mkU64(0x00000040),
-                                         unop(Iop_Clz64, getIReg(rs))));
-                  break;
+#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
+
+      case 0x08: { /* BNEZALC, BNEC, BNVC */
+         if (rs == 0) { /* BNEZALC */
+            DIP("bnezalc r%u, %u", rt, imm);
+
+            if (mode64) {
+               dis_branch_compact(True,
+                                  unop(Iop_Not1,
+                                       binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
+                                  imm, dres);
+            } else {
+               dis_branch_compact(True,
+                                  unop(Iop_Not1,
+                                       binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
+                                  imm, dres);
             }
-            break;
-         }
-      }
+         } else if (rs < rt) { /* BNEC */
+            DIP("bnec r%u, %u", rt, imm);
 
-      case 0x13:  {  /* MTLO */
-         if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
-            /* If DSP is present -> DSP ASE MTLO */
-            UInt retVal = disDSPInstr_MIPS_WRK ( cins );
-            if (0 != retVal ) {
-               goto decode_failure;
+            if (mode64) {
+               dis_branch_compact(False,
+                                  unop(Iop_Not1,
+                                       binop(Iop_CmpEQ64,
+                                             getIReg(rt), getIReg(rs))),
+                                  imm, dres);
+            } else {
+               dis_branch_compact(False,
+                                  unop(Iop_Not1,
+                                       binop(Iop_CmpEQ32,
+                                             getIReg(rt), getIReg(rs))),
+                                  imm, dres);
             }
-            break;
-         } else {
-            switch (sa) {
-               case 0:
-                  DIP("mtlo r%u", rs);
-                  if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
-                      !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
-                     ILLEGAL_INSTRUCTON;
-                  }
-                  putLO(getIReg(rs));
-                  break;
-               case 1:
-                  DIP("dclo r%u, r%u", rd, rs);
-                  t1 = newTemp(Ity_I1);
-                  assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
-                                                 mkU64(0xffffffffffffffffULL)));
-                  putIReg(rd, IRExpr_ITE(mkexpr(t1),
-                                         mkU64(0x40),
-                                         unop(Iop_Clz64, unop(Iop_Not64,
-                                                              getIReg(rs)))));
-               break;
+         } else { /* BNVC */
+            DIP("bnvc r%u, r%u, %u", rs, rt, imm);
+
+            if (mode64) {
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           getIReg(rt),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      getIReg(rt),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           getIReg(rs),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      getIReg(rs),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
+                                           binop(Iop_Add64,
+                                                 getIReg(rt), getIReg(rs)),
+                                           mkU64(0xffffffff80000000ULL)),
+                                     mkU32(1),
+                                     IRExpr_ITE(binop(Iop_CmpLT64S,
+                                                      binop(Iop_Add64,
+                                                            getIReg(rt),
+                                                            getIReg(rs)),
+                                                      mkU64(0x7FFFFFFFULL)),
+                                                mkU32(0), mkU32(1))));
+               assign(t3, binop(Iop_Add32,
+                                mkexpr(t0),
+                                binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
+               dis_branch_compact(False,
+                                  binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
+                                  imm, dres);
+            } else {
+               IRTemp tmpRs32 = newTemp(Ity_I32);
+               IRTemp tmpRt32 = newTemp(Ity_I32);
+
+               assign(tmpRs32, getIReg(rs));
+               assign(tmpRt32, getIReg(rt));
+               t0 = newTemp(Ity_I32);
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               t4 = newTemp(Ity_I32);
+               /* dst = src0 + src1
+                  if (sign(src0 ) != sign(src1 ))
+                  goto no overflow;
+                  if (sign(dst) == sign(src0 ))
+                  goto no overflow;
+                  we have overflow! */
+
+               assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+               assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+               assign(t2, unop(Iop_1Uto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+                                     mkU32(0x80000000))));
+
+               assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+               assign(t4, unop(Iop_1Uto32,
+                               binop(Iop_CmpNE32,
+                                     binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+                                     mkU32(0x80000000))));
+
+               dis_branch_compact(False, binop(Iop_CmpNE32 ,
+                                               binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+                                               mkU32(0)), imm, dres);
             }
-            break;
          }
+
+         break;
       }
 
-      case 0x21:  /* ADDU */
-         DIP("addu r%u, r%u, r%u", rd, rs, rt);
-         if (mode64) {
-            ALU_PATTERN64(Iop_Add32);
-         } else {
-            ALU_PATTERN(Iop_Add32);
-         }
+#endif
+
+      case 0x09:  /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
+         DIP("daddiu r%u, r%u, %u", rt, rs, imm);
+         putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
          break;
 
-      case 0x22: {  /* SUB */
-         DIP("sub r%u, r%u, r%u", rd, rs, rt);
-         IRTemp tmpRs32 = newTemp(Ity_I32);
-         IRTemp tmpRt32 = newTemp(Ity_I32);
+      case 0x0A: {  /* LDL */
+         /* Load Doubleword Left - LDL; MIPS64 */
+         vassert(mode64);
+         DIP("ldl r%u, %u(r%u)", rt, imm, rs);
+         /* t1 = addr */
+#if defined (_MIPSEL)
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
+                          mkU64(extend_s_16to64(imm)))));
+#endif
+         /* t2 = word addr */
+         /* t4 = addr mod 8 */
+         LWX_SWX_PATTERN64_1;
 
-         assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
-         assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         t2 = newTemp(Ity_I32);
-         t3 = newTemp(Ity_I32);
-         t4 = newTemp(Ity_I32);
-         t5 = newTemp(Ity_I32);
-         /* dst = src0 + (-1 * src1)
-            if(sign(src0 ) != sign((-1 * src1) ))
-            goto no overflow;
-            if(sign(dst) == sign(src0 ))
-            goto no overflow;
-            we have overflow! */
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I64);
+         assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
+                          narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
+                                                 mkexpr(t4)), mkU8(3)))));
 
-         assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
-         assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
-         assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
-         assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
-                         mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+         /* rt content  - adjusted */
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I64);
 
-         assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
-         assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
-                         mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+         assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
 
-         stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
-                                mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
-                          mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
-                                   IRConst_U32(guest_PC_curr_instr + 4),
-                          OFFB_PC));
+         assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
+                          narrowTo(Ity_I8, mkexpr(t5))));
 
-         putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
+         assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
+
+         putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
          break;
       }
-      case 0x23:  /* SUBU */
-         DIP("subu r%u, r%u, r%u", rd, rs, rt);
-         if (mode64) {
-            ALU_PATTERN64(Iop_Sub32);
+
+      case 0x0B: {  /* LDR */
+         /* Load Doubleword Right - LDR; MIPS64 */
+         vassert(mode64);
+         DIP("ldr r%u,%u(r%u)", rt, imm, rs);
+         /* t1 = addr */
+#if defined (_MIPSEL)
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
+                          mkU64(extend_s_16to64(imm)))));
+#endif
+         /* t2 = word addr */
+         /* t4 = addr mod 8 */
+         LWX_SWX_PATTERN64_1;
+
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I64);
+         assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
+                          narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
+
+         /* rt content  - adjusted */
+         t5 = newTemp(Ity_I64);
+         assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
+                          binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
+                                narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
+
+         putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
+         break;
+      }
+
+      case 0x0C:  /* Special2 */
+         return disInstr_MIPS_WRK_Special2(cins, archinfo, abiinfo, dres, bstmt, lastn,
+                                           resteerOkFn, callback_opaque);
+
+      case 0x0D: /* DAUI */
+         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            DIP("daui  r%u, r%u, %x", rt, rs, imm);
+            putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
          } else {
-            ALU_PATTERN(Iop_Sub32);
+            ILLEGAL_INSTRUCTON
+         }
+
+         break;
+
+      case 0x0E: /* MIPS MSA (SIMD) */
+         if (has_msa) {
+            Int retVal = disMSAInstr_MIPS_WRK(cins);
+
+            if (retVal == 0) {
+               break;
+            } else if (retVal == -2) {
+               ILLEGAL_INSTRUCTON
+               break;
+            }
          }
+
+         vex_printf("Error occured while trying to decode MIPS MSA "
+                    "instruction.\nYour platform probably doesn't support "
+                    "MIPS MSA (SIMD) ASE.\n");
+         return -1;
+
+      case 0x0F:  /* Special3 */
+         return disInstr_MIPS_WRK_Special3(cins, archinfo, abiinfo, dres, bstmt, lastn,
+                                           resteerOkFn, callback_opaque);
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disInstr_MIPS_WRK_20(UInt cins)
+{
+   IRTemp t1 = 0, t2, t3, t4, t5;
+   UInt opcode, rs, rt, imm;
+
+   opcode = get_opcode(cins);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+   switch (opcode & 0x0F) {
+      case 0x00:  /* LB */
+         DIP("lb r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         if (mode64)
+            putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
+         else
+            putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
+
          break;
 
-      case 0x24:  /* AND */
-         DIP("and r%u, r%u, r%u", rd, rs, rt);
-         if (mode64) {
-            ALU_PATTERN(Iop_And64);
-         } else {
-            ALU_PATTERN(Iop_And32);
-         }
+      case 0x01:  /* LH */
+         DIP("lh r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         if (mode64)
+            putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
+         else
+            putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
+
          break;
 
-      case 0x25:  /* OR */
-         DIP("or r%u, r%u, r%u", rd, rs, rt);
+      case 0x02:  /* LWL */
+         DIP("lwl r%u, %u(r%u)", rt, imm, rs);
+
          if (mode64) {
-            ALU_PATTERN(Iop_Or64);
+            /* t1 = addr */
+            t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
+            assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+            assign(t1, binop(Iop_Xor64,
+                             mkU64(0x03),
+                             binop(Iop_Add64,
+                                   getIReg(rs),
+                                   mkU64(extend_s_16to64(imm)))));
+#endif
+            /* t2 = word addr */
+            /* t4 = addr mod 4 */
+            LWX_SWX_PATTERN64;
+
+            /* t3 = word content - shifted */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_Shl32,
+                             load(Ity_I32, mkexpr(t2)),
+                             narrowTo(Ity_I8,
+                                      binop(Iop_Shl32,
+                                            binop(Iop_Sub32,
+                                                  mkU32(0x03),
+                                                  mkexpr(t4)),
+                                            mkU8(3)))));
+
+            /* rt content - adjusted */
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_And32,
+                             mkNarrowTo32(ty, getIReg(rt)),
+                             binop(Iop_Shr32,
+                                   mkU32(0x00FFFFFF),
+                                   narrowTo(Ity_I8, binop(Iop_Mul32,
+                                            mkU32(0x08),
+                                            mkexpr(t4))))));
+
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+                                                mkexpr(t3)), True));
          } else {
-            ALU_PATTERN(Iop_Or32);
+            /* t1 = addr */
+            t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+            assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+            assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                             mkU32(extend_s_16to32(imm)))));
+#endif
+
+            /* t2 = word addr */
+            /* t4 = addr mod 4 */
+            LWX_SWX_PATTERN;
+
+            /* t3 = word content - shifted */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
+                             binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
+                                   mkU8(3)))));
+
+            /* rt content  - adjusted */
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_And32,
+                             getIReg(rt),
+                             binop(Iop_Shr32,
+                                   mkU32(0x00FFFFFF),
+                                   narrowTo(Ity_I8, binop(Iop_Mul32,
+                                            mkU32(0x08),
+                                            mkexpr(t4))))));
+
+            putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
          }
+
          break;
 
-      case 0x26:  /* XOR */
-         DIP("xor r%u, r%u, r%u", rd, rs, rt);
-         if (mode64) {
-            ALU_PATTERN(Iop_Xor64);
-         } else {
-            ALU_PATTERN(Iop_Xor32);
-         }
+      case 0x03:  /* LW */
+         DIP("lw r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
          break;
 
-      case 0x27:  /* NOR */
-         DIP("nor r%u, r%u, r%u", rd, rs, rt);
+      case 0x04:  /* LBU */
+         DIP("lbu r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
          if (mode64)
-            putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
-                                              getIReg(rt))));
+            putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
          else
-            putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
-                                              getIReg(rt))));
+            putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
+
          break;
 
-      case 0x08:  /* JR */
-         DIP("jr r%u", rs);
-         t0 = newTemp(ty);
-         assign(t0, getIReg(rs));
-         lastn = mkexpr(t0);
+      case 0x05:  /* LHU */
+         DIP("lhu r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         if (mode64)
+            putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
+         else
+            putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
+
          break;
 
-      case 0x09:  /* JALR */
-         DIP("jalr r%u r%u", rd, rs);
+      case 0x06:  /* LWR */
+         DIP("lwr r%u, %u(r%u)", rt, imm, rs);
+
          if (mode64) {
-            putIReg(rd, mkU64(guest_PC_curr_instr + 8));
-            t0 = newTemp(Ity_I64);
-            assign(t0, getIReg(rs));
-            lastn = mkexpr(t0);
+            /* t1 = addr */
+            t1 = newTemp(Ity_I64);
+
+#if defined (_MIPSEL)
+            assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+            assign(t1, binop(Iop_Xor64,
+                             mkU64(0x3),
+                             binop(Iop_Add64,
+                                   getIReg(rs),
+                                   mkU64(extend_s_16to64(imm)))));
+#endif
+            /* t2 = word addr */
+            /* t4 = addr mod 4 */
+            LWX_SWX_PATTERN64;
+
+            /* t3 = word content - shifted */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_Shr32,
+                             load(Ity_I32, mkexpr(t2)),
+                             narrowTo(Ity_I8,
+                                      binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
+
+            /* rt content  - adjusted */
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+                             unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
+                                                   narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+            putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+                                                mkexpr(t3)), True));
+
          } else {
-            putIReg(rd, mkU32(guest_PC_curr_instr + 8));
-            t0 = newTemp(Ity_I32);
-            assign(t0, getIReg(rs));
-            lastn = mkexpr(t0);
+            /* t1 = addr */
+            t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+            assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+            assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                             mkU32(extend_s_16to32(imm)))));
+#endif
+
+            /* t2 = word addr */
+            /* t4 = addr mod 4 */
+            LWX_SWX_PATTERN;
+
+            /* t3 = word content - shifted */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
+                             narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
+                                                    mkU8(3)))));
+
+            /* rt content  - adjusted */
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
+                             binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+                                   binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+            putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
          }
-         break;
 
-      case 0x0C:  /* SYSCALL */
-         DIP("syscall");
-         if (mode64)
-            putPC(mkU64(guest_PC_curr_instr + 4));
-         else
-            putPC(mkU32(guest_PC_curr_instr + 4));
-         dres.jk_StopHere = Ijk_Sys_syscall;
-         dres.whatNext    = Dis_StopHere;
          break;
 
-      case 0x2A:  /* SLT */
-         DIP("slt r%u, r%u, r%u", rd, rs, rt);
-         if (mode64)
-            putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
-                                               getIReg(rt))));
-         else
-            putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
-                                               getIReg(rt))));
+      case 0x07:  /* Load Word unsigned - LWU; MIPS64 */
+         DIP("lwu r%u,%u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
          break;
 
-      case 0x2B:  /* SLTU */
-         DIP("sltu r%u, r%u, r%u", rd, rs, rt);
-         if (mode64)
-            putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
-                                         getIReg(rt))));
-         else
-            putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
-                                         getIReg(rt))));
+      case 0x08:  /* SB */
+         DIP("sb r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
          break;
 
-      case 0x00: {  /* SLL */
-         DIP("sll r%u, r%u, %u", rd, rt, sa);
-         IRTemp tmpRt32 = newTemp(Ity_I32);
-         IRTemp tmpSh32 = newTemp(Ity_I32);
-         IRTemp tmpRd = newTemp(Ity_I64);
-         if (mode64) {
-            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-            assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
-            assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
-            putIReg(rd, mkexpr(tmpRd));
-         } else
-            SXX_PATTERN(Iop_Shl32);
+      case 0x09:  /* SH */
+         DIP("sh r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
          break;
-      }
 
-      case 0x04: {  /* SLLV */
-         DIP("sllv r%u, r%u, r%u", rd, rt, rs);
+      case 0x0A:  /* SWL */
+         DIP("swl r%u, %u(r%u)", rt, imm, rs);
+
          if (mode64) {
-            IRTemp tmpRs8 = newTemp(Ity_I8);
-            IRTemp tmpRt32 = newTemp(Ity_I32);
-            IRTemp tmpSh32 = newTemp(Ity_I32);
-            IRTemp tmp = newTemp(ty);
-            assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
-                              mkSzImm(ty, 31)));
-            assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
-            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-            assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
-            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+            IRTemp E_byte = newTemp(Ity_I8);
+            IRTemp F_byte = newTemp(Ity_I8);
+            IRTemp G_byte = newTemp(Ity_I8);
+            IRTemp H_byte = newTemp(Ity_I8);
+            IRTemp F_pos  = newTemp(Ity_I64);
+            IRTemp G_pos  = newTemp(Ity_I64);
+
+            /* H byte */
+            assign(H_byte, getByteFromReg(rt, 0));
+            /* G byte */
+            assign(G_byte, getByteFromReg(rt, 1));
+            /* F byte */
+            assign(F_byte, getByteFromReg(rt, 2));
+            /* E byte */
+            assign(E_byte, getByteFromReg(rt, 3));
+
+            /* t1 = addr */
+            t1 = newTemp(Ity_I64);
+            assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+            /* t2 = word addr */
+            t2 = newTemp(Ity_I64);
+            assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+
+            /* t3 = addr mod 4 */
+            t3 = newTemp(Ity_I64);
+            assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+
+#if defined (_MIPSEL)
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                     mkU64(0x0),
+                                     mkU64(0x1)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+                                     mkU64(0x1),
+                                     mkU64(0x0)));
+
+            /* Store X_byte on the right place. */
+            store(mkexpr(t2), mkexpr(H_byte));
+            store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+            store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+            store(mkexpr(t1), mkexpr(E_byte));
+
+#else    /* _MIPSEB */
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+                                     mkU64(0x0),
+                                     mkU64(0x1)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                     mkU64(0x2),
+                                     mkU64(0x3)));
+
+            store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
+            store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+            store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+            store(mkexpr(t1), mkexpr(E_byte));
+
+#endif
          } else {
-            SXXV_PATTERN(Iop_Shl32);
+            IRTemp E_byte = newTemp(Ity_I8);
+            IRTemp F_byte = newTemp(Ity_I8);
+            IRTemp G_byte = newTemp(Ity_I8);
+            IRTemp H_byte = newTemp(Ity_I8);
+            IRTemp F_pos  = newTemp(Ity_I32);
+            IRTemp G_pos  = newTemp(Ity_I32);
+
+            /* H byte */
+            assign(H_byte, getByteFromReg(rt, 0));
+            /* G byte */
+            assign(G_byte, getByteFromReg(rt, 1));
+            /* F byte */
+            assign(F_byte, getByteFromReg(rt, 2));
+            /* E byte */
+            assign(E_byte, getByteFromReg(rt, 3));
+
+            /* t1 = addr */
+            t1 = newTemp(Ity_I32);
+            assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+
+            /* t2 = word addr */
+            t2 = newTemp(Ity_I32);
+            assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+
+            /* t3 = addr mod 4 */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+
+#if defined (_MIPSEL)
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+                                     mkU32(0x0),
+                                     mkU32(0x1)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+                                     mkU32(0x1),
+                                     mkU32(0x0)));
+
+            /* Store X_byte on the right place. */
+            store(mkexpr(t2), mkexpr(H_byte));
+            store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+            store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+            store(mkexpr(t1), mkexpr(E_byte));
+
+#else    /* _MIPSEB */
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+                                     mkU32(0x0),
+                                     mkU32(0x1)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+                                     mkU32(0x2),
+                                     mkU32(0x3)));
+
+            store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
+            store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+            store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+            store(mkexpr(t1), mkexpr(E_byte));
+
+#endif
          }
+
          break;
-      }
 
-      case 0x03:  /* SRA */
-         DIP("sra r%u, r%u, %u", rd, rt, sa);
-         if (mode64) {
-            IRTemp tmpRt32 = newTemp(Ity_I32);
-            IRTemp tmpSh32 = newTemp(Ity_I32);
+      case 0x0B:  /* SW */
+         DIP("sw r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
+         break;
+
+      case 0x0C: {  /* SDL rt, offset(base) MIPS64 */
+         DIP("sdl r%u, %u(r%u)", rt, imm, rs);
+         vassert(mode64);
+         IRTemp A_byte = newTemp(Ity_I8);
+         IRTemp B_byte = newTemp(Ity_I8);
+         IRTemp C_byte = newTemp(Ity_I8);
+         IRTemp D_byte = newTemp(Ity_I8);
+         IRTemp E_byte = newTemp(Ity_I8);
+         IRTemp F_byte = newTemp(Ity_I8);
+         IRTemp G_byte = newTemp(Ity_I8);
+         IRTemp H_byte = newTemp(Ity_I8);
+         IRTemp B_pos  = newTemp(Ity_I64);
+         IRTemp C_pos  = newTemp(Ity_I64);
+         IRTemp D_pos  = newTemp(Ity_I64);
+         IRTemp E_pos  = newTemp(Ity_I64);
+         IRTemp F_pos  = newTemp(Ity_I64);
+         IRTemp G_pos  = newTemp(Ity_I64);
+
+         /* H byte */
+         assign(H_byte, getByteFromReg(rt, 0));
+         /* G byte */
+         assign(G_byte, getByteFromReg(rt, 1));
+         /* F byte */
+         assign(F_byte, getByteFromReg(rt, 2));
+         /* E byte */
+         assign(E_byte, getByteFromReg(rt, 3));
+         /* D byte */
+         assign(D_byte, getByteFromReg(rt, 4));
+         /* C byte */
+         assign(C_byte, getByteFromReg(rt, 5));
+         /* B byte */
+         assign(B_byte, getByteFromReg(rt, 6));
+         /* A byte */
+         assign(A_byte, getByteFromReg(rt, 7));
+
+         /* t1 = addr */
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+         /* t2 = word addr */
+         t2 = newTemp(Ity_I64);
+         assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
+
+         /* t3 = addr mod 7 */
+         t3 = newTemp(Ity_I64);
+         assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+
+#if defined (_MIPSEL)
+         /* Calculate X_byte position. */
+         assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
+                                  mkU64(0x0),
+                                  mkU64(0x1)));
+
+         assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
+                                  mkU64(0x0),
+                                  mkU64(0x2)));
+
+         assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
+                                  mkU64(0x0),
+                                  mkU64(0x3)));
+
+         assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
+                                  mkU64(0x0),
+                                  mkU64(0x4)));
+
+         assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
+                                  mkU64(0x0),
+                                  mkU64(0x5)));
+
+         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+                                  mkU64(0x1),
+                                  mkU64(0x0)));
+
+         /* Store X_byte on the right place. */
+         store(mkexpr(t2), mkexpr(H_byte));
+         store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+         store(mkexpr(t1), mkexpr(A_byte));
+
+#else /* _MIPSEB */
+         /* Calculate X_byte position. */
+         assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+                                  mkU64(0x0),
+                                  mkU64(0x1)));
+
+         assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
+                                  mkU64(0x2),
+                                  mkU64(0x0)));
+
+         assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
+                                  mkU64(0x3),
+                                  mkU64(0x0)));
 
-            t1 = newTemp(Ity_I64);
-            t2 = newTemp(Ity_I64);
-            t3 = newTemp(Ity_I64);
+         assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
+                                  mkU64(0x4),
+                                  mkU64(0x0)));
 
-            assign(t1, binop(Iop_And64, getIReg(rt),  /* hi */
-                             mkU64(0xFFFFFFFF00000000ULL)));
+         assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
+                                  mkU64(0x5),
+                                  mkU64(0x0)));
 
-            assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
+         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                  mkU64(0x6),
+                                  mkU64(0x7)));
 
-            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-            assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
+         /* Store X_byte on the right place. */
+         store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
+         store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+         store(mkexpr(t1), mkexpr(A_byte));
+#endif
 
-            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
-         } else {
-            SXX_PATTERN(Iop_Sar32);
-         }
          break;
+      }
 
-      case 0x07:  /* SRAV */
-         DIP("srav r%u, r%u, r%u", rd, rt, rs);
-         if (mode64) {
-            IRTemp tmpRt32 = newTemp(Ity_I32);
-            IRTemp tmpSh32 = newTemp(Ity_I32);
+      case 0x0D: {
+         /* SDR rt, offset(base) - MIPS64 */
+         vassert(mode64);
+         DIP("sdr r%u, %u(r%u)", rt, imm, rs);
+         IRTemp A_byte = newTemp(Ity_I8);
+         IRTemp B_byte = newTemp(Ity_I8);
+         IRTemp C_byte = newTemp(Ity_I8);
+         IRTemp D_byte = newTemp(Ity_I8);
+         IRTemp E_byte = newTemp(Ity_I8);
+         IRTemp F_byte = newTemp(Ity_I8);
+         IRTemp G_byte = newTemp(Ity_I8);
+         IRTemp H_byte = newTemp(Ity_I8);
+         IRTemp B_pos  = newTemp(Ity_I64);
+         IRTemp C_pos  = newTemp(Ity_I64);
+         IRTemp D_pos  = newTemp(Ity_I64);
+         IRTemp E_pos  = newTemp(Ity_I64);
+         IRTemp F_pos  = newTemp(Ity_I64);
+         IRTemp G_pos  = newTemp(Ity_I64);
 
-            t1 = newTemp(Ity_I64);
-            t2 = newTemp(Ity_I64);
-            t3 = newTemp(Ity_I64);
-            t4 = newTemp(Ity_I8);
+         /* H byte */
+         assign(H_byte, getByteFromReg(rt, 0));
+         /* G byte */
+         assign(G_byte, getByteFromReg(rt, 1));
+         /* F byte */
+         assign(F_byte, getByteFromReg(rt, 2));
+         /* E byte */
+         assign(E_byte, getByteFromReg(rt, 3));
+         /* D byte */
+         assign(D_byte, getByteFromReg(rt, 4));
+         /* C byte */
+         assign(C_byte, getByteFromReg(rt, 5));
+         /* B byte */
+         assign(B_byte, getByteFromReg(rt, 6));
+         /* A byte */
+         assign(A_byte, getByteFromReg(rt, 7));
 
-            assign(t4, unop(Iop_32to8, binop(Iop_And32,
-                       mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
+         /* t1 = addr */
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
 
-            assign(t1, binop(Iop_And64, getIReg(rt),  /* hi */
-                   mkU64(0xFFFFFFFF00000000ULL)));
+         /* t2 = word addr */
+         t2 = newTemp(Ity_I64);
+         assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
 
-            assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
+         /* t3 = addr mod 7 */
+         t3 = newTemp(Ity_I64);
+         assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
 
-            assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-            assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
+#if defined (_MIPSEL)
+         /* Calculate X_byte position. */
+         assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
+                                  mkU64(0x0),
+                                  mkU64(0x6)));
 
-            putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
-         } else {
-            SXXV_PATTERN(Iop_Sar32);
-         }
-         break;
+         assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
+                                  mkU64(0x0),
+                                  mkU64(0x5)));
 
-      case 0x02: {  /* SRL */
-         rot = get_rot(cins);
-         if (rot) {
-            DIP("rotr r%u, r%u, %u", rd, rt, sa);
-            putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
-                        getIReg(rt)), sa), True));
-         } else {
-            DIP("srl r%u, r%u, %u", rd, rt, sa);
-            if (mode64) {
-               IRTemp tmpSh32 = newTemp(Ity_I32);
-               IRTemp tmpRt32 = newTemp(Ity_I32);
+         assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
+                                  mkU64(0x0),
+                                  mkU64(0x4)));
 
-               assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
-               assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
-               putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
-            } else {
-               SXX_PATTERN(Iop_Shr32);
-            }
-         }
-      break;
-      }
+         assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
+                                  mkU64(0x0),
+                                  mkU64(0x3)));
 
-      case 0x06: {
-         rot = get_rotv(cins);
-         if (rot) {
-            DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
-            putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
-                        getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
-            break;
-         } else {  /* SRLV */
-            DIP("srlv r%u, r%u, r%u", rd, rt, rs);
-            if (mode64) {
-               SXXV_PATTERN64(Iop_Shr32);
-            } else {
-               SXXV_PATTERN(Iop_Shr32);
-            }
-            break;
-         }
-      }
-      case 0x05: { /* LSA */
-         UInt imm2 = (imm & 0xC0) >> 6;
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
-            DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
-            if (mode64) {
-               DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
-               putIReg(rd, unop(Iop_32Sto64,
-                                binop(Iop_Add32,
-                                      binop(Iop_Shl32,
-                                            unop(Iop_64to32, getIReg(rs)),
-                                            mkU8(imm2 + 1)),
-                                      unop(Iop_64to32, getIReg(rt)))));
-               break;
-            } else {
-               DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
-               putIReg(rd, binop(Iop_Add32,
-                                 binop(Iop_Shl32,
-                                       getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
-               break;
-            }
-         } else {
-            ILLEGAL_INSTRUCTON;
-            break;
-         }
+         assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
+                                  mkU64(0x0),
+                                  mkU64(0x2)));
 
-      }
-      case 0x15:{ /* DLSA */
-         UInt imm2 = (imm & 0xC0) >> 6;
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
-            DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
-            putIReg(rd, binop(Iop_Add64,
-                              binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
-                              getIReg(rt)));
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-         break;
-      }
+         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+                                  mkU64(0x0),
+                                  mkU64(0x1)));
 
-      case 0x0D:  /* BREAK */
-         DIP("break 0x%x", trap_code);
-         if (mode64)
-            jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
-         else
-            jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
-         vassert(dres.whatNext == Dis_StopHere);
-         break;
+         /* Store X_byte on the right place. */
+         store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+         store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+         store(mkexpr(t1), mkexpr(H_byte));
 
-      case 0x30: {  /* TGE */
-         DIP("tge r%u, r%u %u", rs, rt, trap_code);
-         if (mode64) {
-            if (trap_code == 7)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                Ijk_SigFPE_IntDiv,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                Ijk_SigFPE_IntOvf,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                Ijk_SigTRAP,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-         } else {
-            if (trap_code == 7)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntDiv,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else if (trap_code == 6)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntOvf,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32S,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigTRAP,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-         }
-         break;
-      }
-      case 0x31: {  /* TGEU */
-         DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
-         if (mode64) {
-            if (trap_code == 7)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntDiv,
-                                  IRConst_U64(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else if (trap_code == 6)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntOvf,
-                                  IRConst_U64(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT64U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigTRAP,
-                                  IRConst_U64(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-         } else {
-            if (trap_code == 7)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntDiv,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else if (trap_code == 6)
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigFPE_IntOvf,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-            else
-               stmt (IRStmt_Exit (unop (Iop_Not1,
-                                        binop (Iop_CmpLT32U,
-                                               getIReg (rs),
-                                               getIReg (rt))),
-                                  Ijk_SigTRAP,
-                                  IRConst_U32(guest_PC_curr_instr + 4),
-                                  OFFB_PC));
-         }
+#else /* _MIPSEB */
+         /* Calculate X_byte position. */
+         assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
+                                  mkU64(0x6),
+                                  mkU64(0x0)));
+
+         assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
+                                  mkU64(0x5),
+                                  mkU64(0x0)));
+
+         assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
+                                  mkU64(0x4),
+                                  mkU64(0x0)));
+
+         assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
+                                  mkU64(0x3),
+                                  mkU64(0x0)));
+
+         assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
+                                  mkU64(0x2),
+                                  mkU64(0x0)));
+
+         assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                  mkU64(0x0),
+                                  mkU64(0x1)));
+
+         /* Store X_byte on the right place. */
+         store(mkexpr(t2), mkexpr(A_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+         store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+         store(mkexpr(t1), mkexpr(H_byte));
+#endif
          break;
       }
-      case 0x32: {  /* TLT */
-         DIP("tlt r%u, r%u %u", rs, rt, trap_code);
+
+      case 0x0E:  /* SWR */
+         DIP("swr r%u, %u(r%u)", rt, imm, rs);
+
          if (mode64) {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+            IRTemp E_byte = newTemp(Ity_I8);
+            IRTemp F_byte = newTemp(Ity_I8);
+            IRTemp G_byte = newTemp(Ity_I8);
+            IRTemp H_byte = newTemp(Ity_I8);
+            IRTemp F_pos  = newTemp(Ity_I64);
+            IRTemp G_pos  = newTemp(Ity_I64);
+
+            /* H byte */
+            assign(H_byte, getByteFromReg(rt, 0));
+            /* G byte */
+            assign(G_byte, getByteFromReg(rt, 1));
+            /* F byte */
+            assign(F_byte, getByteFromReg(rt, 2));
+            /* E byte */
+            assign(E_byte, getByteFromReg(rt, 3));
+
+            /* t1 = addr */
+            t1 = newTemp(Ity_I64);
+            assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+            /* t2 = word addr */
+            t2 = newTemp(Ity_I64);
+            assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+
+            /* t3 = addr mod 4 */
+            t3 = newTemp(Ity_I64);
+            assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+
+#if defined (_MIPSEL)
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                     mkU64(0x2),
+                                     mkU64(0x3)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+                                     mkU64(0x0),
+                                     mkU64(0x1)));
+
+            /* Store X_byte on the right place. */
+            store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
+            store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+            store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+            store(mkexpr(t1), mkexpr(H_byte));
+
+#else    /* _MIPSEB */
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+                                     mkU64(0x1),
+                                     mkU64(0x0)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+                                     mkU64(0x0),
+                                     mkU64(0x1)));
+
+            /* Store X_byte on the right place. */
+            store(mkexpr(t2), mkexpr(E_byte));
+            store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+            store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+            store(mkexpr(t1), mkexpr(H_byte));
+#endif
          } else {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+            IRTemp E_byte = newTemp(Ity_I8);
+            IRTemp F_byte = newTemp(Ity_I8);
+            IRTemp G_byte = newTemp(Ity_I8);
+            IRTemp H_byte = newTemp(Ity_I8);
+            IRTemp F_pos  = newTemp(Ity_I32);
+            IRTemp G_pos  = newTemp(Ity_I32);
+
+            /* H byte */
+            assign(H_byte, getByteFromReg(rt, 0));
+            /* G byte */
+            assign(G_byte, getByteFromReg(rt, 1));
+            /* F byte */
+            assign(F_byte, getByteFromReg(rt, 2));
+            /* E byte */
+            assign(E_byte, getByteFromReg(rt, 3));
+
+            /* t1 = addr */
+            t1 = newTemp(Ity_I32);
+            assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+
+            /* t2 = word addr */
+            t2 = newTemp(Ity_I32);
+            assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+
+            /* t3 = addr mod 4 */
+            t3 = newTemp(Ity_I32);
+            assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+
+#if defined (_MIPSEL)
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+                                     mkU32(0x2),
+                                     mkU32(0x3)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+                                     mkU32(0x0),
+                                     mkU32(0x1)));
+
+            /* Store X_byte on the right place. */
+            store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
+            store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+            store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+            store(mkexpr(t1), mkexpr(H_byte));
+
+#else    /* _MIPSEB */
+            /* Calculate X_byte position. */
+            assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+                                     mkU32(0x1),
+                                     mkU32(0x0)));
+
+            assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+                                     mkU32(0x0),
+                                     mkU32(0x1)));
+
+            /* Store X_byte on the right place. */
+            store(mkexpr(t2), mkexpr(E_byte));
+            store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+            store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+            store(mkexpr(t1), mkexpr(H_byte));
+#endif
          }
+
          break;
-      }
-      case 0x33: {  /* TLTU */
-         DIP("tltu r%u, r%u %u", rs, rt, trap_code);
-         if (mode64) {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+   }
+
+   return 0;
+}
+
+static UInt disInstr_MIPS_WRK_30(UInt cins, const VexArchInfo* archinfo,
+                                 const VexAbiInfo*  abiinfo, DisResult* dres,
+                                 IRStmt** bstmt)
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5;
+   UInt opcode, rs, rt, rd, ft, function, imm, instr_index;
+
+   opcode = get_opcode(cins);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   ft = get_ft(cins);
+
+   instr_index = get_instr_index(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+   switch (opcode & 0x0F) {
+      case 0x00:  /* LL */
+         DIP("ll r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         if (abiinfo->guest__use_fallback_LLSC) {
+            t2 = newTemp(ty);
+            assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+            putLLaddr(mkexpr(t1));
+            putLLdata(mkexpr(t2));
+            putIReg(rt, mkexpr(t2));
          } else {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
-                                      getIReg (rt)), Ijk_SigTRAP,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+            t2 = newTemp(Ity_I32);
+            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
+            putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
          }
+
          break;
-      }
-      case 0x34: {  /* TEQ */
-         DIP("teq r%u, r%u, %u", rs, rt, trap_code);
-         if (mode64) {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+
+      case 0x01:  /* LWC1 */
+         /* Load Word to Floating Point - LWC1 (MIPS32) */
+         DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
+         LOAD_STORE_PATTERN;
+
+         if (fp_mode64) {
+            t0 = newTemp(Ity_F32);
+            t2 = newTemp(Ity_I64);
+            assign(t0, load(Ity_F32, mkexpr(t1)));
+            assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+                                                   mkexpr(t0)), True));
+            putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
          } else {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
+            putFReg(ft, load(Ity_F32, mkexpr(t1)));
          }
+
          break;
-      }
-      case 0x35: {   /* SELEQZ */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
-            if (mode64) {
-               putIReg(rd, binop(Iop_And64,
-                                 unop(Iop_Not64,
-                                      unop(Iop_CmpwNEZ64, getIReg(rt))),
-                                 getIReg(rs)));
+
+      case 0x02:  /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
+
+         /* Cavium Specific instructions. */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            assign(t0, mkU32(0x1));
+            assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
+            dis_branch(False, binop(Iop_CmpEQ32,
+                                    binop(Iop_And32,
+                                          mkexpr(t1),
+                                          mkNarrowTo32(ty, getIReg(rs))),
+                                    mkU32(0x0)),
+                       imm, bstmt);
+         } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("bc  %x", instr_index & 0x3FFFFFF);
+
+               if (mode64) {
+                  t0 = newTemp(Ity_I64);
+                  assign(t0, mkU64(guest_PC_curr_instr +
+                                   ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
+               } else {
+                  t0 = newTemp(Ity_I32);
+                  assign(t0, mkU32(guest_PC_curr_instr +
+                                   ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
+               }
+
+               putPC(mkexpr(t0));
+               dres->whatNext = Dis_StopHere;
+               dres->jk_StopHere = Ijk_Boring;
             } else {
-               putIReg(rd, binop(Iop_And32,
-                                 unop(Iop_Not32,
-                                      unop(Iop_CmpwNEZ32, getIReg(rt))),
-                                 getIReg(rs)));
+               ILLEGAL_INSTRUCTON;
+               break;
             }
          } else {
-            ILLEGAL_INSTRUCTON;
+            return -1;
          }
+
          break;
-      }
 
-      case 0x36: {  /* TNE */
-         DIP("tne r%u, r%u %u", rs, rt, trap_code);
-         if (mode64) {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U64(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-         } else {
-            if (trap_code == 7)
-               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntDiv,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else if (trap_code == 6)
-               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigFPE_IntOvf,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-            else
-               stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
-                                      getIReg(rt)), Ijk_SigTRAP,
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                                OFFB_PC));
-         }
+      case 0x03:  /* PREF */
+         DIP("pref");
          break;
-      }
-      case 0x37:  { /* SELNEZ */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("selnez r%u, r%u, r%u", rd, rs, rt);
-            if (mode64) {
-               putIReg(rd, binop(Iop_And64,
-                                 unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
+
+      case 0x04:  /* Load Linked Doubleword - LLD; MIPS64 */
+         DIP("lld r%u, %u(r%u)", rt, imm, rs);
+
+         if (mode64) {
+            LOAD_STORE_PATTERN;
+            t2 = newTemp(Ity_I64);
+
+            if (abiinfo->guest__use_fallback_LLSC) {
+               assign(t2, load(Ity_I64, mkexpr(t1)));
+               putLLaddr(mkexpr(t1));
+               putLLdata(mkexpr(t2));
             } else {
-               putIReg(rd, binop(Iop_And32,
-                                 unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
+               stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
             }
+
+            putIReg(rt, mkexpr(t2));
          } else {
-            ILLEGAL_INSTRUCTON;
+            ILLEGAL_INSTRUCTON
          }
-         break;
-      }
-      case 0x14:
-      case 0x16:
-      case 0x17:  /* DSLLV, DROTRV:DSRLV, DSRAV */
-      case 0x38:
-      case 0x3A:
-      case 0x3B:  /* DSLL, DROTL:DSRL, DSRA  */
-      case 0x3C:
-      case 0x3E:
-      case 0x3F:  /* DSLL32, DROTR32:DSRL32, DSRA32 */
-         if (dis_instr_shrt(cins))
-            break;
-         goto decode_failure;
 
-      case 0x0F:  /* SYNC */
-         DIP("sync 0x%x", sel);
-         /* Just ignore it. */
          break;
 
-      case 0x2C: {  /* Doubleword Add - DADD; MIPS64 */
-         DIP("dadd r%u, r%u, r%u", rd, rs, rt);
-         IRTemp tmpRs64 = newTemp(Ity_I64);
-         IRTemp tmpRt64 = newTemp(Ity_I64);
+      case 0x05:  /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
+         DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         putDReg(ft, load(Ity_F64, mkexpr(t1)));
+         break;
 
-         assign(tmpRs64, getIReg(rs));
-         assign(tmpRt64, getIReg(rt));
+      case 0x06:  /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
 
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I64);
-         t2 = newTemp(Ity_I64);
-         t3 = newTemp(Ity_I64);
-         t4 = newTemp(Ity_I64);
-         /* dst = src0 + src1
-            if(sign(src0 ) != sign(src1 ))
-            goto no overflow;
-            if(sign(dst) == sign(src0 ))
-            goto no overflow;
-            we have overflow! */
+         /* Cavium Specific instructions. */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
+            t0 = newTemp(Ity_I64);
+            t1 = newTemp(Ity_I8);  /* Shift. */
+            t2 = newTemp(Ity_I64);
+            assign(t0, mkU64(0x1));
+            assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
+            assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
+            dis_branch(False, binop(Iop_CmpEQ64,
+                                    binop(Iop_And64,
+                                          mkexpr(t2),
+                                          getIReg(rs)),
+                                    mkU64(0x0)),
+                       imm, bstmt);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) { /* JIC */
+               DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
 
-         assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
-         assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
-         assign(t2, unop(Iop_1Uto64,
-                         binop(Iop_CmpEQ64,
-                               binop(Iop_And64, mkexpr(t1),
-                                     mkU64(0x8000000000000000ULL)),
-                               mkU64(0x8000000000000000ULL))));
+               if (mode64) {
+                  t0 = newTemp(Ity_I64);
+                  assign(t0, binop(Iop_Add64, getIReg(rt),
+                                   mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
+               } else {
+                  t0 = newTemp(Ity_I32);
+                  assign(t0, binop(Iop_Add32, getIReg(rt),
+                                   mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
+               }
 
-         assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
-         assign(t4, unop(Iop_1Uto64,
-                         binop(Iop_CmpNE64,
-                               binop(Iop_And64, mkexpr(t3),
-                                     mkU64(0x8000000000000000ULL)),
-                               mkU64(0x8000000000000000ULL))));
+               putPC(mkexpr(t0));
+               dres->whatNext = Dis_StopHere;
+               dres->jk_StopHere = Ijk_Boring;
+            } else { /* BEQZC */
+               DIP("beqzc r%u, %u", rs, imm);
+               dres->jk_StopHere = Ijk_Boring;
+               dres->whatNext = Dis_StopHere;
+               ULong branch_offset;
+               t0 = newTemp(Ity_I1);
 
-         stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
-                                binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
-                                mkU64(0)),
-                          Ijk_SigFPE_IntOvf,
-                          IRConst_U64(guest_PC_curr_instr + 4),
-                          OFFB_PC));
+               if (mode64) {
+                  branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
+                  assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
+                  stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                                   IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+                                   OFFB_PC));
+                  putPC(mkU64(guest_PC_curr_instr + 4));
+               } else {
+                  branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
+                  assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
+                  stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                                   IRConst_U32(guest_PC_curr_instr + 4 +
+                                               (UInt) branch_offset), OFFB_PC));
+                  putPC(mkU32(guest_PC_curr_instr + 4));
+               }
+            }
+         } else {
+            ILLEGAL_INSTRUCTON
+         }
 
-         putIReg(rd,  mkexpr(t0));
          break;
-      }
 
-      case 0x2D:  /* Doubleword Add Unsigned - DADDU; MIPS64 */
-         DIP("daddu r%u, r%u, r%u", rd, rs, rt);
-         ALU_PATTERN(Iop_Add64);
+      case 0x07:  /* Load Doubleword - LD; MIPS64 */
+         DIP("ld r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         putIReg(rt, load(Ity_I64, mkexpr(t1)));
          break;
 
-      case 0x2E: {  /* Doubleword Subtract - DSUB; MIPS64 */
-         DIP("dsub r%u, r%u, r%u", rd, rs, rt);
-         IRTemp tmpRs64 = newTemp(Ity_I64);
-         IRTemp tmpRt64 = newTemp(Ity_I64);
+      case 0x08:  /* SC */
+         DIP("sc r%u, %u(r%u)", rt, imm, rs);
+         t2 = newTemp(Ity_I1);
+         LOAD_STORE_PATTERN;
 
-         assign(tmpRs64, getIReg(rs));
-         assign(tmpRt64, getIReg(rt));
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I64);
-         t2 = newTemp(Ity_I64);
-         t3 = newTemp(Ity_I64);
-         t4 = newTemp(Ity_I64);
-         t5 = newTemp(Ity_I64);
-         /* dst = src0 + (-1 * src1)
-            if(sign(src0 ) != sign((-1 * src1) ))
-            goto no overflow;
-            if(sign(dst) == sign(src0 ))
-            goto no overflow;
-            we have overflow! */
+         if (abiinfo->guest__use_fallback_LLSC) {
+            t3 = newTemp(Ity_I32);
+            assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                             mkexpr(t1), getLLaddr()));
+            assign(t3, mkNarrowTo32(ty, getIReg(rt)));
+            putLLaddr(LLADDR_INVALID);
+            putIReg(rt, getIReg(0));
 
-         assign(t5, binop(Iop_Mul64,
-                          mkexpr(tmpRt64),
-                          mkU64(0xffffffffffffffffULL)));
-         assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
-         assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
-         assign(t2, unop(Iop_1Sto64,
-                         binop(Iop_CmpEQ64,
-                               binop(Iop_And64,
-                                     mkexpr(t1),
-                                     mkU64(0x8000000000000000ULL)),
-                               mkU64(0x8000000000000000ULL))));
+            mips_next_insn_if(mkexpr(t2));
 
-         assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
-         assign(t4, unop(Iop_1Sto64,
-                         binop(Iop_CmpNE64,
-                               binop(Iop_And64,
-                                     mkexpr(t3),
-                                     mkU64(0x8000000000000000ULL)),
-                               mkU64(0x8000000000000000ULL))));
+            t4 = newTemp(Ity_I32);
+            t5 = newTemp(Ity_I32);
 
-         stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
-                                mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
-                          IRConst_U64(guest_PC_curr_instr + 4),
-                          OFFB_PC));
+            assign(t5, mkNarrowTo32(ty, getLLdata()));
+
+            stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+                                    MIPS_IEND, mkexpr(t1),                 /* addr */
+                                    NULL, mkexpr(t5),                      /* expected value */
+                                    NULL, mkexpr(t3)                       /* new value */)));
+
+            putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
+                             binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
+         } else {
+            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
+                             mkNarrowTo32(ty, getIReg(rt))));
+            putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
+         }
 
-         putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
          break;
-      }
 
-      case 0x2F:  /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
-         DIP("dsub r%u, r%u,r%u", rd, rt, rt);
-         ALU_PATTERN(Iop_Sub64);
+      case 0x09:  /* SWC1 */
+         DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
+
+         if (fp_mode64) {
+            t0 = newTemp(Ity_I64);
+            t2 = newTemp(Ity_I32);
+            LOAD_STORE_PATTERN;
+            assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
+            assign(t2, unop(Iop_64to32, mkexpr(t0)));
+            store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
+         } else {
+            LOAD_STORE_PATTERN;
+            store(mkexpr(t1), getFReg(ft));
+         }
+
          break;
 
-      default:
-         goto decode_failure;
-      }
-      break;
+      case 0x0A:  /* Branch on Bit Set - BBIT1; Cavium OCTEON */
 
-   case 0x01:  /* Regimm */
+         /* Cavium Specific instructions. */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            assign(t0, mkU32(0x1));
+            assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
+            dis_branch(False, binop(Iop_CmpNE32,
+                                    binop(Iop_And32,
+                                          mkexpr(t1),
+                                          mkNarrowTo32(ty, getIReg(rs))),
+                                    mkU32(0x0)),
+                       imm, bstmt);
+         } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("balc  %x", instr_index & 0x3FFFFFF);
+
+               if (mode64) {
+                  t0 = newTemp(Ity_I64);
+                  assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(
+                        instr_index & 0x3FFFFFF) + 1) << 2)));
+                  putIReg(31, mkU64(guest_PC_curr_instr + 4));
+               } else {
+                  t0 = newTemp(Ity_I32);
+                  assign(t0, mkU32(guest_PC_curr_instr + ((extend_s_26to32(
+                        instr_index & 0x3FFFFFF) + 1) << 2)));
+                  putIReg(31, mkU32(guest_PC_curr_instr + 4));
+               }
+
+               putPC(mkexpr(t0));
+               dres->whatNext = Dis_StopHere;
+               dres->jk_StopHere = Ijk_Call;
+            } else {
+               ILLEGAL_INSTRUCTON;
+               break;
+            }
+         } else {
+            return -1;
+         }
 
-      switch (rt) {
-      case 0x00:  /* BLTZ */
-         DIP("bltz r%u, %u", rs, imm);
-         if (mode64) {
-            if (!dis_instr_branch(cins, &dres, resteerOkFn,
-                        callback_opaque, &bstmt))
-               goto decode_failure;
-         } else
-            dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
-                       mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
          break;
 
-      case 0x01:  /* BGEZ */
-         DIP("bgez r%u, %u", rs, imm);
+      case 0x0B:  /* PCREL */
+         if (rt == 0x1E) { /* AUIPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("auipc r%u, %u", rs, imm);
+
+               if (mode64) {
+                  putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
+               } else {
+                  putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
+
+            break;
+         } else if (rt == 0x1F) { /* ALUIPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("aluipc r%u, %u", rs, imm);
+
+               if (mode64) {
+                  putIReg(rs, mkU64((~0x0FFFFULL) &
+                                    (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
+               } else {
+                  putIReg(rs, mkU32((~0x0FFFFULL) &
+                                    (guest_PC_curr_instr + (imm << 16))));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
+
+            break;
+         } else if ((rt & 0x18) == 0) { /* ADDIUPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
+
+               if (mode64) {
+                  putIReg(rs, mkU64(guest_PC_curr_instr +
+                                    (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+               } else {
+                  putIReg(rs, mkU32(guest_PC_curr_instr +
+                                    (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
+
+            break;
+         } else if ((rt & 0x18) == 8) { /* LWPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
+
+               if (mode64) {
+                  t1 = newTemp(Ity_I64);
+                  assign(t1, mkU64(guest_PC_curr_instr +
+                                   (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+                  putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
+               } else {
+                  t1 = newTemp(Ity_I32);
+                  assign(t1, mkU32(guest_PC_curr_instr +
+                                   (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+                  putIReg(rs, load(Ity_I32, mkexpr(t1)));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON;
+            }
+
+            break;
+         } else if ((rt & 0x18) == 16) { /* LWUPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
+
+               if (mode64) {
+                  t1 = newTemp(Ity_I64);
+                  assign(t1, mkU64(guest_PC_curr_instr +
+                                   (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+                  putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
+               } else {
+                  t1 = newTemp(Ity_I32);
+                  assign(t1, mkU32(guest_PC_curr_instr +
+                                   (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+                  putIReg(rs, load(Ity_I32, mkexpr(t1)));
+               }
+            } else {
+               ILLEGAL_INSTRUCTON
+            }
+
+            break;
+         } else if ((rt & 0x1C) == 0x18) { /* LDPC */
+            if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+               DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
+               t1 = newTemp(Ity_I64);
+               assign(t1, mkU64(guest_PC_curr_instr +
+                                (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
+               putIReg(rs, load(Ity_I64, mkexpr(t1)));
+            } else {
+               ILLEGAL_INSTRUCTON
+            }
+
+            break;
+         } else {
+            return -1;
+         }
+
+         if (0x3B == function &&
+               (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
+            /*RDHWR*/
+            DIP("rdhwr r%u, r%u", rt, rd);
+
+            if (rd == 29) {
+               putIReg(rt, getULR());
+            } else
+               return -1;
+
+            break;
+         } else {
+            return -1;
+         }
+
+      case 0x0C:  /* Store Conditional Doubleword - SCD; MIPS64 */
+         DIP("scd r%u, %u(r%u)", rt, imm, rs);
+
          if (mode64) {
-            if (!dis_instr_branch(cins, &dres, resteerOkFn,
-                                  callback_opaque, &bstmt))
-               goto decode_failure;
-         } else
-            dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
-                              mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
-         break;
+            t2 = newTemp(Ity_I1);
+            LOAD_STORE_PATTERN;
 
-      case 0x02:  /* BLTZL */
-         DIP("bltzl r%u, %u", rs, imm);
-         lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                     binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
-                     mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
-                     mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
-                     imm);
-         break;
+            if (abiinfo->guest__use_fallback_LLSC) {
+               t3 = newTemp(Ity_I64);
+               assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
+               assign(t3, getIReg(rt));
+               putLLaddr(LLADDR_INVALID);
+               putIReg(rt, getIReg(0));
 
-      case 0x03:  /* BGEZL */
-         DIP("bgezl r%u, %u", rs, imm);
-         lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                     binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
-                     mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
-                     mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
-         break;
+               mips_next_insn_if(mkexpr(t2));
 
-      case 0x10:  /* BLTZAL */
-         DIP("bltzal r%u, %u", rs, imm);
-         if (mode64) {
-            if (!dis_instr_branch(cins, &dres, resteerOkFn,
-                        callback_opaque, &bstmt))
-               goto decode_failure;
-         } else
-            dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
-                       mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
-         break;
+               t4 = newTemp(Ity_I64);
+               t5 = newTemp(Ity_I64);
 
-      case 0x12:  /* BLTZALL */
-         DIP("bltzall r%u, %u", rs, imm);
-         putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
-                              mkU32(guest_PC_curr_instr + 8));
-         lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                     binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
-                     mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
-                     mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
-                     imm);
-         break;
+               assign(t5, getLLdata());
 
-      case 0x11:  /* BGEZAL */
-         DIP("bgezal r%u, %u", rs, imm);
-         if (mode64) {
-            if (!dis_instr_branch(cins, &dres, resteerOkFn,
-                        callback_opaque, &bstmt))
-               goto decode_failure;
-         } else
-            dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
-                       mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
-         break;
+               stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+                                       MIPS_IEND, mkexpr(t1),                 /* addr */
+                                       NULL, mkexpr(t5),                      /* expected value */
+                                       NULL, mkexpr(t3)                       /* new value */)));
 
-      case 0x13:  /* BGEZALL */
-         DIP("bgezall r%u, %u", rs, imm);
-         if (mode64) {
-            putIReg(31, mkU64(guest_PC_curr_instr + 8));
-            lastn = dis_branch_likely(binop(Iop_CmpNE64,
-                                            binop(Iop_And64,
-                                                  getIReg(rs),
-                                                  mkU64(0x8000000000000000ULL)),
-                                            mkU64(0x0)),
-                                      imm);
+               putIReg(rt, unop(Iop_1Uto64,
+                                binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
+            } else {
+               stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
+               putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
+            }
          } else {
-            putIReg(31, mkU32(guest_PC_curr_instr + 8));
-            lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
-                                      getIReg(rs), mkU32(0x80000000)),
-                                      mkU32(0x0)), imm);
+            ILLEGAL_INSTRUCTON
          }
-         break;
 
-      case 0x08:  /* TGEI */
-         DIP("tgei r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit(unop(Iop_Not1,
-                                   binop(Iop_CmpLT64S,
-                                         getIReg(rs),
-                                         mkU64(extend_s_16to64 (imm)))),
-                             Ijk_SigTRAP,
-                             IRConst_U64(guest_PC_curr_instr + 4),
-                             OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit(unop(Iop_Not1,
-                                   binop(Iop_CmpLT32S,
-                                   getIReg(rs),
-                                   mkU32(extend_s_16to32 (imm)))),
-                             Ijk_SigTRAP,
-                             IRConst_U32(guest_PC_curr_instr + 4),
-                             OFFB_PC));
-         }
          break;
 
-      case 0x09: {  /* TGEIU */
-         DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit (unop (Iop_Not1,
-                                     binop (Iop_CmpLT64U,
-                                            getIReg (rs),
-                                            mkU64 (extend_s_16to64 (imm)))),
-                             Ijk_SigTRAP,
-                             IRConst_U64(guest_PC_curr_instr + 4),
-                             OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit (unop (Iop_Not1,
-                                     binop (Iop_CmpLT32U,
-                                            getIReg (rs),
-                                            mkU32 (extend_s_16to32 (imm)))),
-                               Ijk_SigTRAP,
-                               IRConst_U32(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         }
-         break;
-      }
-      case 0x0A: {  /* TLTI */
-         DIP("tlti r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
-                                      mkU64 (extend_s_16to64 (imm))),
-                             Ijk_SigTRAP,
-                             IRConst_U64(guest_PC_curr_instr + 4),
-                             OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
-                                      mkU32 (extend_s_16to32 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U32(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         }
-         break;
-      }
-      case 0x0B: {  /* TLTIU */
-         DIP("tltiu r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
-                                      mkU64 (extend_s_16to64 (imm))),
-                             Ijk_SigTRAP,
-                             IRConst_U64(guest_PC_curr_instr + 4),
-                             OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
-                                      mkU32 (extend_s_16to32 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U32(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         }
-         break;
-      }
-      case 0x0C: {  /* TEQI */
-          DIP("teqi r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
-                                      mkU64 (extend_s_16to64 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U64(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
-                                      mkU32 (extend_s_16to32 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U32(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         }
-         break;
-      }
-      case 0x0E: {  /* TNEI */
-         DIP("tnei r%u, %u %u", rs, imm, trap_code);
-         if (mode64) {
-            stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
-                                      mkU64 (extend_s_16to64 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U64(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         } else {
-            stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
-                                      mkU32 (extend_s_16to32 (imm))),
-                               Ijk_SigTRAP,
-                               IRConst_U32(guest_PC_curr_instr + 4),
-                               OFFB_PC));
-         }
-         break;
-      }
-      case 0x1C: {  /* BPOSGE32 */
-         DIP("bposge32 %u", imm);
-         vassert(!mode64);
-         t0 = newTemp(Ity_I32);
-         /* Get pos field from DSPControl register. */
-         assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-         dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
-                                mkU32(32))), imm, &bstmt);
-      }
-      case 0x1F:
-         /* SYNCI */
-         /* Just ignore it */
+      case 0x0D:  /* Store Doubleword from Floating Point - SDC1 */
+         DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
+         LOAD_STORE_PATTERN;
+         store(mkexpr(t1), getDReg(ft));
          break;
 
-      case 0x06: { /* DAHI */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("dahi  r%u,  %x", rs, imm);
-            putIReg(rs, binop(Iop_Add64,
-                              getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
+      case 0x0E:  /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
+
+         /* Cavium Specific instructions. */
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
+            t0 = newTemp(Ity_I64);
+            t1 = newTemp(Ity_I8);  /* Shift. */
+            t2 = newTemp(Ity_I64);
+            assign(t0, mkU64(0x1));
+            assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
+            assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
+            dis_branch(False, binop(Iop_CmpNE64,
+                                    binop(Iop_And64,
+                                          mkexpr(t2),
+                                          getIReg(rs)),
+                                    mkU64(0x0)),
+                       imm, bstmt);
+         } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+            if (rs == 0) {/* JIALC */
+               DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
+
+               if (rs) return -1;
+
+               if (mode64) {
+                  t0 = newTemp(Ity_I64);
+                  assign(t0, binop(Iop_Add64, getIReg(rt),
+                                   mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
+                  putIReg(31, mkU64(guest_PC_curr_instr + 4));
+               } else {
+                  t0 = newTemp(Ity_I32);
+                  assign(t0, binop(Iop_Add32, getIReg(rt),
+                                   mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
+                  putIReg(31, mkU32(guest_PC_curr_instr + 4));
+               }
+
+               putPC(mkexpr(t0));
+               dres->whatNext = Dis_StopHere;
+               dres->jk_StopHere = Ijk_Call;
+            } else { /* BNEZC */
+               DIP("bnezc r%u, %u", rs, imm);
+               dres->jk_StopHere = Ijk_Boring;
+               dres->whatNext = Dis_StopHere;
+               ULong branch_offset;
+               t0 = newTemp(Ity_I1);
+
+               if (mode64) {
+                  branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
+                  assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
+                  stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                                   IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+                                   OFFB_PC));
+                  putPC(mkU64(guest_PC_curr_instr + 4));
+               } else {
+                  branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
+                  assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
+                  stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+                                   IRConst_U32(guest_PC_curr_instr + 4 +
+                                               (UInt) branch_offset), OFFB_PC));
+                  putPC(mkU32(guest_PC_curr_instr + 4));
+               }
+            }
          } else {
-            ILLEGAL_INSTRUCTON;
+            return -1;
          }
+
          break;
-      }
 
-      case 0x1E: { /* DATI */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("dati  r%u,  %x", rs, imm);
-            putIReg(rs, binop(Iop_Add64,
-                              getIReg(rs), mkU64((long long)imm << 48)));
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
+      case 0x0F:  /* Store Doubleword - SD; MIPS64 */
+         DIP("sd r%u, %u(r%u)", rt, imm, rs);
+         LOAD_STORE_PATTERN;
+         store(mkexpr(t1), getIReg(rt));
          break;
-      }
 
       default:
-         goto decode_failure;
-      }
-      break;
+         return -1;
+   }
 
-   case 0x04:
-      DIP("beq r%u, r%u, %u", rs, rt, imm);
-      if (mode64)
-         dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
-                                 imm, &bstmt);
-      else
-         dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
-                                 imm, &bstmt);
-      break;
-
-   case 0x14:
-      DIP("beql r%u, r%u, %u", rs, rt, imm);
-      lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                                getIReg(rs), getIReg(rt)), imm);
-      break;
-
-   case 0x05:
-      DIP("bne r%u, r%u, %u", rs, rt, imm);
-      if (mode64)
-         dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
-                                 imm, &bstmt);
-      else
-         dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
-                                 imm, &bstmt);
-      break;
-
-   case 0x15:
-      DIP("bnel r%u, r%u, %u", rs, rt, imm);
-      lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
-                                      getIReg(rs), getIReg(rt)), imm);
-      break;
-
-   case 0x07:  /* BGTZ, BGTZALC, BLTZALC, BLTUC */
-      if (rt == 0) { /* BGTZ */
-         DIP("bgtz r%u, %u", rs, imm);
-         if (mode64)
-            dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
-                                   mkU64(0x00))), imm, &bstmt);
-         else
-            dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
-                                   mkU32(0x00))), imm, &bstmt);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         if (rs == 0) { /* BGTZALC */
-            DIP("bgtzalc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(True,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE64S,
-                                             getIReg(rt), mkU64(0x0))),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(True,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE32S,
-                                             getIReg(rt), mkU32(0x0))),
-                                  imm, &dres);
-            }
-         } else if (rs == rt) { /* BLTZALC */
-            DIP("bltzalc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(True,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE64S,
-                                             mkU64(0x0), getIReg(rt))),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(True,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE32S,
-                                             mkU32(0x0), getIReg(rt))),
-                                  imm, &dres);
-            }
-         } else { /* BLTUC */
-            DIP("bltuc r%u, r%u, %u", rt, rs, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
-                                  imm, &dres);
-            }
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
+   return 0;
+}
 
-   case 0x17:  /* BGTZL, BGTZC, BLTZC, BLTC */
-      if (rt == 0) { /* BGTZL */
-         DIP("bgtzl r%u, %u", rs, imm);
-         if (mode64)
-            lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
-                                            mkU64(0x00)), imm);
-         else
-            lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
-                                            mkU32(0x00)), imm);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         if (rs == 0) { /* BGTZC */
-            DIP("bgtzc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE64S,
-                                             getIReg(rt), mkU64(0x0))),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE32S,
-                                             getIReg(rt), mkU32(0x0))),
-                                  imm, &dres);
-            }
-         } else if (rs == rt) { /* BLTZC */
-            DIP("bltzc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE64S,
-                                             mkU64(0x0), getIReg(rt))),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE32S,
-                                             mkU32(0x0), getIReg(rt))),
-                                  imm, &dres);
-            }
-         } else { /* BLTC */
-            DIP("bltc r%u, r%u, %u", rs, rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE64S,
-                                             getIReg(rt), getIReg(rs))),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLE32S,
-                                             getIReg(rt), getIReg(rs))),
-                                  imm, &dres);
-            }
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
+static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
+                                     Addr),
+                                     Bool         resteerCisOk,
+                                     void*        callback_opaque,
+                                     Long         delta64,
+                                     const VexArchInfo* archinfo,
+                                     const VexAbiInfo*  abiinfo,
+                                     Bool         sigill_diag )
+{
 
-   case 0x06:  /* BLEZ, BLEZALC, BGEZALC, BGEUC */
-      if (rt == 0) { /* BLEZ */
-         DIP("blez r%u, %u", rs, imm);
-         if (mode64)
-            dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
-                                   imm, &bstmt);
-         else
-            dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
-                                   &bstmt);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         if (rs == 0) { /* BLEZALC */
-            DIP("blezalc r%u, %u", rt, imm);
-            if (mode64)
-               dis_branch_compact(True,
-                                  binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
-                                  imm, &dres);
-            else
-               dis_branch_compact(True,
-                                  binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
-                                  imm, &dres);
-         } else if (rt == rs) {/* BGEZALC */
-            DIP("bgezalc r%u, %u", rt, imm);
-            if (mode64)
-               dis_branch_compact(True,
-                                  binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
-                                  imm, &dres);
-            else
-               dis_branch_compact(True,
-                                  binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
-                                  imm, &dres);
-         } else { /* BGEUC */
-            DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
-            if (mode64)
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLT64U,
-                                             getIReg(rs), getIReg(rt))),
-                                  imm, &dres);
-            else
-               dis_branch_compact(False,
-                                  unop(Iop_Not1,
-                                       binop(Iop_CmpLT32U,
-                                             getIReg(rs), getIReg(rt))),
-                                  imm, &dres);
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
-
-   case 0x16:  /* BLEZL, BLEZC, BGEZC, BGEC */
-      if (rt == 0) { /* BLEZL */
-         DIP("blezl r%u, %u", rs, imm);
-         lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
-                                        Iop_CmpLE32S, getIReg(rs), mode64 ?
-                                        mkU64(0x0) : mkU32(0x0)))), imm);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-          if (rs == 0) { /* BLEZC */
-            DIP("blezc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
-                                  imm, &dres);
-            }
-         } else if (rt == rs) { /* BGEZC */
-            DIP("bgezc r%u, %u", rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
-                                  imm, &dres);
-            }
-         } else { /* BGEC */
-            DIP("bgec r%u, r%u, %u", rs, rt, imm);
-            if (mode64) {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
-                                  imm, &dres);
-            } else {
-               dis_branch_compact(False,
-                                  binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
-                                  imm, &dres);
-            }
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
+   UInt opcode, cins, result;
 
-#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
-   case 0x08: {  /* ADDI */
-      DIP("addi r%u, r%u, %u", rt, rs, imm);
-      IRTemp tmpRs32 = newTemp(Ity_I32);
-      assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+   DisResult dres;
 
-      t0 = newTemp(Ity_I32);
-      t1 = newTemp(Ity_I32);
-      t2 = newTemp(Ity_I32);
-      t3 = newTemp(Ity_I32);
-      t4 = newTemp(Ity_I32);
-      /* dst = src0 + sign(imm)
-         if(sign(src0 ) != sign(imm ))
-         goto no overflow;
-         if(sign(dst) == sign(src0 ))
-         goto no overflow;
-         we have overflow! */
+   static IRExpr *lastn = NULL;  /* last jump addr */
+   static IRStmt *bstmt = NULL;  /* branch (Exit) stmt */
 
-      assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
-                       mkU32(extend_s_16to32(imm))));
-      assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
-                       mkU32(extend_s_16to32(imm))));
-      assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
-                      mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+   /* The running delta */
+   Int delta = (Int) delta64;
 
-      assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
-      assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
-                      mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+   /* Holds eip at the start of the insn, so that we can print
+      consistent error messages for unimplemented insns. */
+   Int delta_start = delta;
 
-      stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
-                             mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
-                       mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
-                                IRConst_U32(guest_PC_curr_instr + 4),
-                       OFFB_PC));
+   /* Are we in a delay slot ? */
+   Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
 
-      putIReg(rt,  mkWidenFrom32(ty, mkexpr(t0), True));
-      break;
-   }
-#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
-   case 0x08: { /* BEQZALC, BEQC, BOVC */
-      if (rs == 0) { /* BEQZALC */
-         DIP("beqzalc r%u, %u", rt, imm);
-         if (mode64) {
-            dis_branch_compact(True,
-                               binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
-                               imm, &dres);
-         } else {
-            dis_branch_compact(True,
-                               binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
-                               imm, &dres);
-         }
-      } else  if (rs < rt) { /* BEQC */
-         DIP("beqc r%u, r%u, %u",rs, rt, imm);
-         if (mode64) {
-            dis_branch_compact(False,
-                               binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
-                               imm, &dres);
-         } else {
-            dis_branch_compact(False,
-                               binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
-                               imm, &dres);
-         }
-      } else { /* BOVC */
-         DIP("bovc r%u, r%u, %u",rs, rt, imm);
-         if (mode64) {
-            t0 = newTemp(Ity_I32);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I32);
-            assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        getIReg(rt),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   getIReg(rt),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0),mkU32(1))));
-            assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        getIReg(rs),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   getIReg(rs),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0), mkU32(1))));
-            assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        binop(Iop_Add64,
-                                              getIReg(rt), getIReg(rs)),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   binop(Iop_Add64,
-                                                         getIReg(rt),
-                                                         getIReg(rs)),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0), mkU32(1))));
-            assign(t3, binop(Iop_Add32,
-                             mkexpr(t0),
-                             binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
-            dis_branch_compact(False,
-                               binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
-                               imm, &dres);
-         } else {
-            IRTemp tmpRs32 = newTemp(Ity_I32);
-            IRTemp tmpRt32 = newTemp(Ity_I32);
-            assign(tmpRs32, getIReg(rs));
-            assign(tmpRt32, getIReg(rt));
+   /* Set result defaults. */
+   dres.whatNext = Dis_Continue;
+   dres.len = 0;
+   dres.continueAt = 0;
+   dres.jk_StopHere = Ijk_INVALID;
+   dres.hint        = Dis_HintNone;
 
-            t0 = newTemp(Ity_I32);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I32);
-            t4 = newTemp(Ity_I32);
-            /* dst = src0 + src1
-               if (sign(src0 ) != sign(src1 ))
-               goto no overflow;
-               if (sign(dst) == sign(src0 ))
-               goto no overflow;
-               we have overflow! */
+   delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
 
-            assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-            assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-            assign(t2, unop(Iop_1Uto32,
-                            binop(Iop_CmpEQ32,
-                                  binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
-                                  mkU32(0x80000000))));
-
-            assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
-            assign(t4, unop(Iop_1Uto32,
-                            binop(Iop_CmpNE32,
-                                  binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
-                                  mkU32(0x80000000))));
-
-            dis_branch_compact(False, binop(Iop_CmpEQ32,
-                                   binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
-                                   mkU32(0)), imm, &dres);
+   const UChar *code = guest_code + delta;
+   cins = getUInt(code);
+   opcode = get_opcode(cins);
+   DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
+
+   if (delta != 0) {
+      if (branch_or_jump(guest_code + delta - 4)) {
+         if (lastn == NULL && bstmt == NULL) {
+            vassert(0);
+         } else {
+            dres.whatNext = Dis_StopHere;
+
+            if (lastn != NULL) {
+               delay_slot_jump = True;
+            } else if (bstmt != NULL) {
+               delay_slot_branch = True;
+            }
          }
       }
-      break;
-      /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
+
+      if (branch_or_link_likely(guest_code + delta - 4)) {
+         likely_delay_slot = True;
+      }
    }
-#endif
 
-   case 0x09:  /* ADDIU */
-      DIP("addiu r%u, r%u, %u", rt, rs, imm);
-      if (mode64) {
-         putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
-                     mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))),
-                     True));
-      } else
-         putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm))));
-      break;
-   case 0x0C:  /* ANDI */
-      DIP("andi r%u, r%u, %u", rt, rs, imm);
-      if (mode64) {
-         ALUI_PATTERN64(Iop_And64);
-      } else {
-         ALUI_PATTERN(Iop_And32);
-      }
-      break;
-
-   case 0x0E:  /* XORI */
-      DIP("xori r%u, r%u, %u", rt, rs, imm);
-      if (mode64) {
-         ALUI_PATTERN64(Iop_Xor64);
-      } else {
-         ALUI_PATTERN(Iop_Xor32);
-      }
-      break;
-
-   case 0x0D:  /* ORI */
-      DIP("ori r%u, r%u, %u", rt, rs, imm);
-      if (mode64) {
-         ALUI_PATTERN64(Iop_Or64);
-      } else {
-         ALUI_PATTERN(Iop_Or32);
-      }
-      break;
-
-   case 0x0A:  /* SLTI */
-      DIP("slti r%u, r%u, %u", rt, rs, imm);
-      if (mode64)
-         putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
-                                            mkU64(extend_s_16to64(imm)))));
-      else
-         putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
-                                            mkU32(extend_s_16to32(imm)))));
-      break;
+   /* Spot "Special" instructions (see comment at top of file). */
+   {
+      /* Spot the 16-byte preamble:
+       ****mips32****
+       "srl $0, $0, 13
+       "srl $0, $0, 29
+       "srl $0, $0, 3
+       "srl $0, $0, 19
 
-   case 0x0B:  /* SLTIU */
-      DIP("sltiu r%u, r%u, %u", rt, rs, imm);
-      if (mode64)
-         putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
-                                            mkU64(extend_s_16to64(imm)))));
-      else
-         putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
-                                            mkU32(extend_s_16to32(imm)))));
-      break;
+       ****mips64****
+       dsll $0, $0, 3
+       dsll $0, $0, 13
+       dsll $0, $0, 29
+       dsll $0, $0, 19 */
 
-#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
-   case 0x18: {  /* Doubleword Add Immidiate - DADDI; MIPS64 */
-      DIP("daddi r%u, r%u, %u", rt, rs, imm);
-      IRTemp tmpRs64 = newTemp(Ity_I64);
-      assign(tmpRs64, getIReg(rs));
+      UInt word1 = mode64 ? 0xF8  : 0x342;
+      UInt word2 = mode64 ? 0x378 : 0x742;
+      UInt word3 = mode64 ? 0x778 : 0xC2;
+      UInt word4 = mode64 ? 0x4F8 : 0x4C2;
 
-      t0 = newTemp(Ity_I64);
-      t1 = newTemp(Ity_I64);
-      t2 = newTemp(Ity_I64);
-      t3 = newTemp(Ity_I64);
-      t4 = newTemp(Ity_I64);
-      /* dst = src0 + sign(imm)
-         if(sign(src0 ) != sign(imm ))
-         goto no overflow;
-         if(sign(dst) == sign(src0 ))
-         goto no overflow;
-         we have overflow! */
+      if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
+            getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
+         /* Got a "Special" instruction preamble. Which one is it? */
+         if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
+            /* $11 = client_request ( $12 ) */
+            DIP("$11 = client_request ( $12 )");
 
-      assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
-                       mkU64(extend_s_16to64(imm))));
-      assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
-                       mkU64(extend_s_16to64(imm))));
-      assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
-                      mkexpr(t1), mkU64(0x8000000000000000ULL)),
-                                        mkU64(0x8000000000000000ULL))));
-
-      assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
-      assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
-                      mkexpr(t3), mkU64(0x8000000000000000ULL)),
-                                        mkU64(0x8000000000000000ULL))));
-
-      stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
-                             mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
-                       IRConst_U64(guest_PC_curr_instr + 4),
-                       OFFB_PC));
+            if (mode64)
+               putPC(mkU64(guest_PC_curr_instr + 20));
+            else
+               putPC(mkU32(guest_PC_curr_instr + 20));
 
-      putIReg(rt,  mkexpr(t0));
-      break;
-   }
-#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
-   case 0x18: { /* BNEZALC, BNEC, BNVC */
-      if (rs == 0) { /* BNEZALC */
-         DIP("bnezalc r%u, %u", rt, imm);
-         if (mode64) {
-            dis_branch_compact(True,
-                               unop(Iop_Not1,
-                                    binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
-                               imm, &dres);
-         } else {
-            dis_branch_compact(True,
-                               unop(Iop_Not1,
-                                    binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
-                               imm, &dres);
-         }
-      } else if (rs < rt) { /* BNEC */
-         DIP("bnec r%u, %u", rt, imm);
-         if (mode64) {
-            dis_branch_compact(False,
-                               unop(Iop_Not1,
-                                    binop(Iop_CmpEQ64,
-                                          getIReg(rt), getIReg(rs))),
-                               imm, &dres);
-         } else {
-            dis_branch_compact(False,
-                               unop(Iop_Not1,
-                                    binop(Iop_CmpEQ32,
-                                          getIReg(rt), getIReg(rs))),
-                               imm, &dres);
-         }
-      } else { /* BNVC */
-         DIP("bnvc r%u, r%u, %u", rs, rt, imm);
-         if (mode64) {
-            t0 = newTemp(Ity_I32);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I32);
-            assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        getIReg(rt),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   getIReg(rt),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0),mkU32(1))));
-            assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        getIReg(rs),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   getIReg(rs),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0),mkU32(1))));
-            assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
-                                        binop(Iop_Add64,
-                                              getIReg(rt), getIReg(rs)),
-                                        mkU64(0xffffffff80000000ULL)),
-                                  mkU32(1),
-                                  IRExpr_ITE(binop(Iop_CmpLT64S,
-                                                   binop(Iop_Add64,
-                                                         getIReg(rt),
-                                                         getIReg(rs)),
-                                                   mkU64(0x7FFFFFFFULL)),
-                                             mkU32(0),mkU32(1))));
-            assign(t3, binop(Iop_Add32,
-                             mkexpr(t0),
-                             binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
-            dis_branch_compact(False,
-                               binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
-                               imm, &dres);
-         } else {
-            IRTemp tmpRs32 = newTemp(Ity_I32);
-            IRTemp tmpRt32 = newTemp(Ity_I32);
+            dres.jk_StopHere = Ijk_ClientReq;
+            dres.whatNext    = Dis_StopHere;
 
-            assign(tmpRs32, getIReg(rs));
-            assign(tmpRt32, getIReg(rt));
-            t0 = newTemp(Ity_I32);
-            t1 = newTemp(Ity_I32);
-            t2 = newTemp(Ity_I32);
-            t3 = newTemp(Ity_I32);
-            t4 = newTemp(Ity_I32);
-            /* dst = src0 + src1
-               if (sign(src0 ) != sign(src1 ))
-               goto no overflow;
-               if (sign(dst) == sign(src0 ))
-               goto no overflow;
-               we have overflow! */
+            goto decode_success;
+         } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
+            /* $11 = guest_NRADDR */
+            DIP("$11 = guest_NRADDR");
+            dres.len = 20;
+            delta += 20;
 
-            assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-            assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
-            assign(t2, unop(Iop_1Uto32,
-                            binop(Iop_CmpEQ32,
-                                  binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
-                                  mkU32(0x80000000))));
-
-            assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
-            assign(t4, unop(Iop_1Uto32,
-                            binop(Iop_CmpNE32,
-                                  binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
-                                  mkU32(0x80000000))));
-
-            dis_branch_compact(False, binop(Iop_CmpNE32 ,
-                                   binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
-                                   mkU32(0)), imm, &dres);
-         }
-      }
-      break;
-   }
-#endif
+            if (mode64)
+               putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
+                                               guest_NRADDR), Ity_I64));
+            else
+               putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
+                                               guest_NRADDR), Ity_I32));
+
+            goto decode_success;
+         } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
+            /*  branch-and-link-to-noredir $25 */
+            DIP("branch-and-link-to-noredir $25");
 
-   case 0x19:  /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
-      DIP("daddiu r%u, r%u, %u", rt, rs, imm);
-      putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-      break;
+            if (mode64)
+               putIReg(31, mkU64(guest_PC_curr_instr + 20));
+            else
+               putIReg(31, mkU32(guest_PC_curr_instr + 20));
 
-   case 0x1A: {
-      /* Load Doubleword Left - LDL; MIPS64 */
-      vassert(mode64);
-      DIP("ldl r%u, %u(r%u)", rt, imm, rs);
-      /* t1 = addr */
+            putPC(getIReg(25));
+            dres.jk_StopHere = Ijk_NoRedir;
+            dres.whatNext    = Dis_StopHere;
+            goto decode_success;
+         } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
+            /* IR injection */
+            DIP("IR injection");
 #if defined (_MIPSEL)
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+            vex_inject_ir(irsb, Iend_LE);
 #elif defined (_MIPSEB)
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
-                                  mkU64(extend_s_16to64(imm)))));
+            vex_inject_ir(irsb, Iend_BE);
 #endif
-      /* t2 = word addr */
-      /* t4 = addr mod 8 */
-      LWX_SWX_PATTERN64_1;
 
-      /* t3 = word content - shifted */
-      t3 = newTemp(Ity_I64);
-      assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
-                 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
-                 mkexpr(t4)), mkU8(3)))));
-
-      /* rt content  - adjusted */
-      t5 = newTemp(Ity_I64);
-      t6 = newTemp(Ity_I64);
-      t7 = newTemp(Ity_I64);
+            if (mode64) {
+               stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
+                               mkU64(guest_PC_curr_instr)));
+               stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
+                               mkU64(20)));
 
-      assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
+               putPC(mkU64(guest_PC_curr_instr + 20));
+            } else {
+               stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
+                               mkU32(guest_PC_curr_instr)));
+               stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
+                               mkU32(20)));
 
-      assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
-                       narrowTo(Ity_I8, mkexpr(t5))));
+               putPC(mkU32(guest_PC_curr_instr + 20));
+            }
 
-      assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
+            dres.whatNext    = Dis_StopHere;
+            dres.jk_StopHere = Ijk_InvalICache;
+            dres.len = 20;
+            delta += 20;
+            goto decode_success;
+         }
 
-      putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
-      break;
+         /* We don't know what it is.  Set opc1/opc2 so decode_failure
+            can print the insn following the Special-insn preamble. */
+         delta += 16;
+         goto decode_failure;
+         /*NOTREACHED*/
+      }
    }
 
-   case 0x1B: {
-      /* Load Doubleword Right - LDR; MIPS64 */
-      vassert(mode64);
-      DIP("ldr r%u,%u(r%u)", rt, imm, rs);
-      /* t1 = addr */
-#if defined (_MIPSEL)
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
-      t1 = newTemp(Ity_I64);
-      assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
-                                  mkU64(extend_s_16to64(imm)))));
-#endif
-      /* t2 = word addr */
-      /* t4 = addr mod 8 */
-      LWX_SWX_PATTERN64_1;
-
-      /* t3 = word content - shifted */
-      t3 = newTemp(Ity_I64);
-      assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
-                 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
-
-      /* rt content  - adjusted */
-      t5 = newTemp(Ity_I64);
-      assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
-                 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
-                 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
-
-      putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
-      break;
-   }
+   switch (opcode & 0x30) {
+      case 0x00:
+         result = disInstr_MIPS_WRK_00(cins, archinfo, abiinfo, &dres, &bstmt, &lastn,
+                                       resteerOkFn, callback_opaque);
 
-   case 0x27:  /* Load Word unsigned - LWU; MIPS64 */
-      DIP("lwu r%u,%u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
+         if (result == -1) goto decode_failure;
 
-      putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
-      break;
+         if (result == -2) goto decode_failure_dsp;
 
-   case 0x30:  /* LL */
-      DIP("ll r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      if (abiinfo->guest__use_fallback_LLSC) {
-         t2 = newTemp(ty);
-         assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
-         putLLaddr(mkexpr(t1));
-         putLLdata(mkexpr(t2));
-         putIReg(rt, mkexpr(t2));
-      } else {
-         t2 = newTemp(Ity_I32);
-         stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
-         putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
-      }
-      break;
+         break;
 
-   case 0x34:  /* Load Linked Doubleword - LLD; MIPS64 */
-      DIP("lld r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         LOAD_STORE_PATTERN;
-         t2 = newTemp(Ity_I64);
-         if (abiinfo->guest__use_fallback_LLSC) {
-            assign(t2, load(Ity_I64, mkexpr(t1)));
-            putLLaddr(mkexpr(t1));
-            putLLdata(mkexpr(t2));
-         } else {
-            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
-         }
-         putIReg(rt, mkexpr(t2));
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
+      case 0x10:
 
-   case 0x38:  /* SC */
-      DIP("sc r%u, %u(r%u)", rt, imm, rs);
-      t2 = newTemp(Ity_I1);
-      LOAD_STORE_PATTERN;
-      if (abiinfo->guest__use_fallback_LLSC) {
-         t3 = newTemp(Ity_I32);
-         assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
-                          mkexpr(t1), getLLaddr()));
-         assign(t3, mkNarrowTo32(ty, getIReg(rt)));
-         putLLaddr(LLADDR_INVALID);
-         putIReg(rt, getIReg(0));
+         result = disInstr_MIPS_WRK_10(cins, archinfo, abiinfo, &dres, &bstmt, &lastn,
+                                       resteerOkFn, callback_opaque);
 
-         mips_next_insn_if(mkexpr(t2));
+         if (result == -1) goto decode_failure;
 
-         t4 = newTemp(Ity_I32);
-         t5 = newTemp(Ity_I32);
+         if (result == -2) goto decode_failure_dsp;
 
-         assign(t5, mkNarrowTo32(ty, getLLdata()));
+         break;
 
-         stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
-              MIPS_IEND, mkexpr(t1),                 /* addr */
-              NULL, mkexpr(t5),                      /* expected value */
-              NULL, mkexpr(t3)                       /* new value */)));
+      case 0x20:
+         result = disInstr_MIPS_WRK_20(cins);
 
-         putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
-                          binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
-      } else {
-         stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
-                          mkNarrowTo32(ty, getIReg(rt))));
-         putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
-      }
-      break;
+         if (result == -1) goto decode_failure;
 
-   case 0x3C:  /* Store Conditional Doubleword - SCD; MIPS64 */
-      DIP("scd r%u, %u(r%u)", rt, imm, rs);
-      if (mode64) {
-         t2 = newTemp(Ity_I1);
-         LOAD_STORE_PATTERN;
-         if (abiinfo->guest__use_fallback_LLSC) {
-            t3 = newTemp(Ity_I64);
-            assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
-            assign(t3, getIReg(rt));
-            putLLaddr(LLADDR_INVALID);
-            putIReg(rt, getIReg(0));
+         if (result == -2) goto decode_failure_dsp;
 
-            mips_next_insn_if(mkexpr(t2));
+         break;
 
-            t4 = newTemp(Ity_I64);
-            t5 = newTemp(Ity_I64);
+      case 0x30:
+         result = disInstr_MIPS_WRK_30(cins, archinfo, abiinfo, &dres, &bstmt);
 
-            assign(t5, getLLdata());
+         if (result == -1) goto decode_failure;
 
-            stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
-                 MIPS_IEND, mkexpr(t1),                 /* addr */
-                 NULL, mkexpr(t5),                      /* expected value */
-                 NULL, mkexpr(t3)                       /* new value */)));
+         if (result == -2) goto decode_failure_dsp;
 
-            putIReg(rt, unop(Iop_1Uto64,
-                             binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
-         } else {
-            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
-            putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
-
-   case 0x37:  /* Load Doubleword - LD; MIPS64 */
-      DIP("ld r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      putIReg(rt, load(Ity_I64, mkexpr(t1)));
-      break;
-
-   case 0x3F:  /* Store Doubleword - SD; MIPS64 */
-      DIP("sd r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-      store(mkexpr(t1), getIReg(rt));
-      break;
-
-   case 0x32:  /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
-      /* Cavium Specific instructions. */
-      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-         DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         assign(t0, mkU32(0x1));
-         assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
-         dis_branch(False, binop(Iop_CmpEQ32,
-                                 binop(Iop_And32,
-                                       mkexpr(t1),
-                                       mkNarrowTo32(ty, getIReg(rs))),
-                                 mkU32(0x0)),
-                    imm, &bstmt);
-      } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("bc  %x", instr_index & 0x3FFFFFF);
-            if (mode64) {
-               t0 = newTemp(Ity_I64);
-               assign(t0, mkU64(guest_PC_curr_instr +
-                      ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
-            } else {
-               t0 = newTemp(Ity_I32);
-               assign(t0, mkU32(guest_PC_curr_instr +
-                      ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
-            }
-            putPC(mkexpr(t0));
-            dres.whatNext = Dis_StopHere;
-            dres.jk_StopHere = Ijk_Boring;
-         } else {
-            ILLEGAL_INSTRUCTON;
-         }
-      } else {
-         goto decode_failure;
-      }
-      break;
-   case 0x36:  /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
-      /* Cavium Specific instructions. */
-      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-         DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I8);  /* Shift. */
-         t2 = newTemp(Ity_I64);
-         assign(t0, mkU64(0x1));
-         assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
-         assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
-         dis_branch(False, binop(Iop_CmpEQ64,
-                                 binop(Iop_And64,
-                                       mkexpr(t2),
-                                       getIReg(rs)),
-                                 mkU64(0x0)),
-                    imm, &bstmt);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         if (rs == 0) { /* JIC */
-            DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
-            if (mode64) {
-               t0 = newTemp(Ity_I64);
-               assign(t0, binop(Iop_Add64, getIReg(rt),
-                                mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
-            } else {
-               t0 = newTemp(Ity_I32);
-               assign(t0, binop(Iop_Add32, getIReg(rt),
-                                mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
-            }
-            putPC(mkexpr(t0));
-            dres.whatNext = Dis_StopHere;
-            dres.jk_StopHere = Ijk_Boring;
-         } else { /* BEQZC */
-            DIP("beqzc r%u, %u", rs, imm);
-            dres.jk_StopHere = Ijk_Boring;
-            dres.whatNext = Dis_StopHere;
-            ULong branch_offset;
-            t0 = newTemp(Ity_I1);
-            if (mode64) {
-               branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
-               assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
-               stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                                  IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
-                                  OFFB_PC));
-               putPC(mkU64(guest_PC_curr_instr + 4));
-            } else {
-               branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
-               assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
-               stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                                  IRConst_U32(guest_PC_curr_instr + 4 +
-                                              (UInt) branch_offset), OFFB_PC));
-               putPC(mkU32(guest_PC_curr_instr + 4));
-            }
-         }
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-   break;
-   case 0x3A:  /* Branch on Bit Set - BBIT1; Cavium OCTEON */
-      /* Cavium Specific instructions. */
-      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-         DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
-         t0 = newTemp(Ity_I32);
-         t1 = newTemp(Ity_I32);
-         assign(t0, mkU32(0x1));
-         assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
-         dis_branch(False, binop(Iop_CmpNE32,
-                                 binop(Iop_And32,
-                                       mkexpr(t1),
-                                       mkNarrowTo32(ty, getIReg(rs))),
-                                 mkU32(0x0)),
-                    imm, &bstmt);
-      } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
-         if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-            DIP("balc  %x", instr_index & 0x3FFFFFF);
-            if (mode64) {
-               t0 = newTemp(Ity_I64);
-               assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(instr_index & 0x3FFFFFF)+1)<<2)));
-               putIReg(31, mkU64(guest_PC_curr_instr + 4));
-            } else {
-               t0 = newTemp(Ity_I32);
-               assign(t0, mkU32(guest_PC_curr_instr+((extend_s_26to32(instr_index & 0x3FFFFFF)+1)<<2)));
-               putIReg(31, mkU32(guest_PC_curr_instr + 4));
-            }
-            putPC(mkexpr(t0));
-            dres.whatNext = Dis_StopHere;
-            dres.jk_StopHere = Ijk_Call;
+         break;
+
+decode_failure_dsp:
+         vex_printf("Error occured while trying to decode MIPS32 DSP "
+                    "instruction.\nYour platform probably doesn't support "
+                    "MIPS32 DSP ASE.\n");
+decode_failure:
+
+         /* All decode failures end up here. */
+         if (sigill_diag)
+            vex_printf("vex mips->IR: unhandled instruction bytes: "
+                       "0x%x 0x%x 0x%x 0x%x\n",
+                       (UInt) getIByte(delta_start + 0),
+                       (UInt) getIByte(delta_start + 1),
+                       (UInt) getIByte(delta_start + 2),
+                       (UInt) getIByte(delta_start + 3));
+
+         /* Tell the dispatcher that this insn cannot be decoded, and so has
+            not been executed, and (is currently) the next to be executed.
+            EIP should be up-to-date since it made so at the start bnezof each
+            insn, but nevertheless be paranoid and update it again right
+            now. */
+         if (mode64) {
+            stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
+                            mkU64(guest_PC_curr_instr)));
+            jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
          } else {
-            ILLEGAL_INSTRUCTON;
-         }
-      } else {
-         goto decode_failure;
-      }
-      break;
-   case 0x3E:  /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
-      /* Cavium Specific instructions. */
-      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
-         DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
-         t0 = newTemp(Ity_I64);
-         t1 = newTemp(Ity_I8);  /* Shift. */
-         t2 = newTemp(Ity_I64);
-         assign(t0, mkU64(0x1));
-         assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
-         assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
-         dis_branch(False, binop(Iop_CmpNE64,
-                                 binop(Iop_And64,
-                                       mkexpr(t2),
-                                       getIReg(rs)),
-                                 mkU64(0x0)),
-                    imm, &bstmt);
-      } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         if (rs == 0) {/* JIALC */
-            DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
-            if (rs) goto decode_failure;
-            if (mode64) {
-               t0 = newTemp(Ity_I64);
-               assign(t0, binop(Iop_Add64, getIReg(rt),
-                                mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
-               putIReg(31, mkU64(guest_PC_curr_instr + 4));
-            } else {
-               t0 = newTemp(Ity_I32);
-               assign(t0, binop(Iop_Add32, getIReg(rt),
-                                mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
-               putIReg(31, mkU32(guest_PC_curr_instr + 4));
-            }
-            putPC(mkexpr(t0));
-            dres.whatNext = Dis_StopHere;
-            dres.jk_StopHere = Ijk_Call;
-         } else { /* BNEZC */
-            DIP("bnezc r%u, %u", rs, imm);
-            dres.jk_StopHere = Ijk_Boring;
-            dres.whatNext = Dis_StopHere;
-            ULong branch_offset;
-            t0 = newTemp(Ity_I1);
-            if (mode64) {
-               branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
-               assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
-               stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                                  IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
-                                  OFFB_PC));
-               putPC(mkU64(guest_PC_curr_instr + 4));
-            } else {
-               branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
-               assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
-               stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
-                                  IRConst_U32(guest_PC_curr_instr + 4 +
-                                              (UInt) branch_offset), OFFB_PC));
-               putPC(mkU32(guest_PC_curr_instr + 4));
-            }
+            stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
+                            mkU32(guest_PC_curr_instr)));
+            jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
          }
-      } else {
-         goto decode_failure;
-      }
-      break;
-
-   case 0x1D: /* DAUI */
-      if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
-         DIP("daui  r%u, r%u, %x", rt, rs, imm);
-         putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
-      } else {
-         ILLEGAL_INSTRUCTON;
-      }
-      break;
 
-   case 0x1E: /* MIPS MSA (SIMD) */
-      if (has_msa) {
-         Int retVal = disMSAInstr_MIPS_WRK(cins);
-         if (retVal == 0) {
-            break;
-         } else if (retVal == -2) {
-            ILLEGAL_INSTRUCTON
-            break;
-         }
-      }
-      vex_printf("Error occured while trying to decode MIPS MSA "
-                 "instruction.\nYour platform probably doesn't support "
-                 "MIPS MSA (SIMD) ASE.\n");
-
-   default:
-      goto decode_failure;
-
-   decode_failure_dsp:
-      vex_printf("Error occured while trying to decode MIPS32 DSP "
-                 "instruction.\nYour platform probably doesn't support "
-                 "MIPS32 DSP ASE.\n");
-   decode_failure:
-      /* All decode failures end up here. */
-      if (sigill_diag)
-         vex_printf("vex mips->IR: unhandled instruction bytes: "
-                    "0x%x 0x%x 0x%x 0x%x\n",
-                    (UInt) getIByte(delta_start + 0),
-                    (UInt) getIByte(delta_start + 1),
-                    (UInt) getIByte(delta_start + 2),
-                    (UInt) getIByte(delta_start + 3));
-
-      /* Tell the dispatcher that this insn cannot be decoded, and so has
-         not been executed, and (is currently) the next to be executed.
-         EIP should be up-to-date since it made so at the start bnezof each
-         insn, but nevertheless be paranoid and update it again right
-         now. */
-      if (mode64) {
-         stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
-              mkU64(guest_PC_curr_instr)));
-         jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
-      } else {
-         stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
-              mkU32(guest_PC_curr_instr)));
-         jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
-      }
-      dres.whatNext = Dis_StopHere;
-      dres.len = 0;
-      return dres;
+         dres.whatNext = Dis_StopHere;
+         dres.len = 0;
+         return dres;
    }  /* switch (opc) for the main (primary) opcode switch. */
 
    /* All MIPS insn have 4 bytes */
@@ -33321,10 +25031,12 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       delay_slot_branch = False;
       stmt(bstmt);
       bstmt = NULL;
+
       if (mode64)
          putPC(mkU64(guest_PC_curr_instr + 4));
       else
          putPC(mkU32(guest_PC_curr_instr + 4));
+
       dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
                          Ijk_Call : Ijk_Boring;
    }
@@ -33335,6 +25047,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
       putPC(lastn);
       lastn = NULL;
    }
+
    if (delay_slot_jump) {
       putPC(lastn);
       lastn = NULL;
@@ -33342,7 +25055,8 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
                          Ijk_Call : Ijk_Boring;
    }
 
- decode_success:
+decode_success:
+
    /* All decode successes end up here. */
    switch (dres.whatNext) {
       case Dis_Continue:
@@ -33350,16 +25064,21 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
             putPC(mkU64(guest_PC_curr_instr + 4));
          else
             putPC(mkU32(guest_PC_curr_instr + 4));
+
          break;
+
       case Dis_ResteerU:
       case Dis_ResteerC:
          if (mode64)
             putPC(mkU64(dres.continueAt));
          else
             putPC(mkU32(dres.continueAt));
+
          break;
+
       case Dis_StopHere:
          break;
+
       default:
          vassert(0);
          break;
@@ -33368,7 +25087,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
    /* On MIPS we need to check if the last instruction in block is branch or
       jump. */
    if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4)
-       &&  (dres.whatNext != Dis_StopHere))
+         &&  (dres.whatNext != Dis_StopHere))
       if (branch_or_jump(guest_code + delta + 4)) {
          dres.whatNext = Dis_StopHere;
          dres.jk_StopHere = Ijk_Boring;
diff --git a/VEX/priv/guest_mipsdsp_toIR.c b/VEX/priv/guest_mipsdsp_toIR.c
new file mode 100644 (file)
index 0000000..430c632
--- /dev/null
@@ -0,0 +1,9688 @@
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+#include "libvex_guest_mips32.h"
+#include "libvex_guest_mips64.h"
+
+#include "main_util.h"
+#include "main_globals.h"
+#include "guest_generic_bb_to_IR.h"
+#include "guest_mips_defs.h"
+#include "mips_defs.h"
+
+
+/* Put value to DSPControl register. Expression e is written to DSPControl as
+   is. If only certain bits of DSPControl need to be changed, it should be done
+   before calling putDSPControl(). It could be done by reading DSPControl and
+   ORing it with appropriate mask. */
+static void putDSPControl(IRExpr * e)
+{
+   vassert(!mode64);
+   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
+}
+
+/* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
+static void putAcc(UInt acNo, IRExpr * e)
+{
+   vassert(!mode64);
+   vassert(acNo <= 3);
+   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
+   stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
+
+   /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
+      between MIPS32 and MIPS DSP ASE insn sets. */
+   if (0 == acNo) {
+      putLO(unop(Iop_64to32, e));
+      putHI(unop(Iop_64HIto32, e));
+   }
+}
+/*------------------------------------------------------------*/
+/*---       Disassemble a single DSP ASE instruction       ---*/
+/*------------------------------------------------------------*/
+
+static UInt disDSPInstr_MIPS_WRK_Special ( UInt cins )
+{
+   IRTemp t1;
+   UInt rs, rt, rd, function, ac, ac_mfhilo;
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   function = get_function(cins);
+   ac = get_acNo(cins);
+   ac_mfhilo = get_acNo_mfhilo(cins);
+
+   switch (function) {
+      case 0x10: {  /* MFHI */
+         DIP("mfhi ac%u r%u", ac_mfhilo, rd);
+         putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
+         break;
+      }
+
+      case 0x11: {  /* MTHI */
+         DIP("mthi ac%u r%u", ac, rs);
+         t1 = newTemp(Ity_I32);
+         assign(t1, unop(Iop_64to32, getAcc(ac)));
+         putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
+         break;
+      }
+
+      case 0x12: {  /* MFLO */
+         DIP("mflo ac%u r%u", ac_mfhilo, rd);
+         putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
+         break;
+      }
+
+      case 0x13: {  /* MTLO */
+         DIP("mtlo ac%u r%u", ac, rs);
+         t1 = newTemp(Ity_I32);
+         assign(t1, unop(Iop_64HIto32, getAcc(ac)));
+         putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
+         break;
+      }
+
+      case 0x18: {  /* MULT */
+         DIP("mult ac%u r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
+                          mkNarrowTo32(Ity_I32, getIReg(rt))));
+         putAcc(ac, mkexpr(t1));
+         break;
+      }
+
+      case 0x19: {  /* MULTU */
+         DIP("multu ac%u r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
+                          mkNarrowTo32(Ity_I32,
+                                       getIReg(rt))));
+         putAcc(ac, mkexpr(t1));
+         break;
+      }
+   }
+
+   return 0;
+}
+
+
+static UInt disDSPInstr_MIPS_WRK_Special2 ( UInt cins )
+{
+   IRTemp t1 = 0, t2, t3;
+   UInt rs, rt, function, ac;
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   function = get_function(cins);
+   ac = get_acNo(cins);
+
+   switch (function) {
+      case 0x00: {  /* MADD */
+         DIP("madd ac%u, r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t1, getAcc(ac));
+         assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+         assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
+
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0x01: {  /* MADDU */
+         DIP("maddu ac%u r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t1, getAcc(ac));
+         assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+         assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
+
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0x04: {  /* MSUB */
+         DIP("msub ac%u r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t1, getAcc(ac));
+         assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+         assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
+
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0x05: {  /* MSUBU */
+         DIP("msubu ac%u r%u, r%u", ac, rs, rt);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t1, getAcc(ac));
+         assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+         assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
+
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_ABSQ_SPH( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
+              t15, t16, t17;
+   UInt   rt, rd, sa, dsp_imm;
+
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+   dsp_imm = get_dspImm(cins);
+
+   switch (sa) {
+      case 0x1: {  /* ABSQ_S.QB */
+         DIP("absq_s.qb r%u, r%u", rd, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I8);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I8);
+         t8 = newTemp(Ity_I8);
+         t9 = newTemp(Ity_I1);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I8);
+         t12 = newTemp(Ity_I8);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I1);
+         t15 = newTemp(Ity_I8);
+         t16 = newTemp(Ity_I32);
+         t17 = newTemp(Ity_I32);
+
+         /* Absolute value of the rightmost byte (bits 7-0). */
+         /* t0 - rightmost byte. */
+         assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
+         /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
+         assign(t1, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32, mkexpr(t0)),
+                          mkU32(0x00000080)));
+         /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
+         assign(t2, unop(Iop_32to1,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     getIReg(rt),
+                                     mkU32(0x00000080)),
+                               mkU8(0x7))));
+         /* t3 holds abs(t0). */
+         assign(t3, IRExpr_ITE(mkexpr(t1),
+                               mkU8(0x7F),
+                               IRExpr_ITE(mkexpr(t2),
+                                          binop(Iop_Add8,
+                                                unop(Iop_Not8,
+                                                      mkexpr(t0)),
+                                                mkU8(0x1)),
+                                          mkexpr(t0))));
+
+         /* Absolute value of bits 15-8. */
+         /* t4 - input byte. */
+         assign(t4,
+                unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
+         /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
+         assign(t5, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32, mkexpr(t4)),
+                          mkU32(0x00000080)));
+         /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
+         assign(t6, unop(Iop_32to1,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     getIReg(rt),
+                                     mkU32(0x00008000)),
+                               mkU8(15))));
+         /* t3 holds abs(t4). */
+         assign(t7, IRExpr_ITE(mkexpr(t5),
+                               mkU8(0x7F),
+                               IRExpr_ITE(mkexpr(t6),
+                                          binop(Iop_Add8,
+                                                unop(Iop_Not8,
+                                                      mkexpr(t4)),
+                                                mkU8(0x1)),
+                                          mkexpr(t4))));
+
+         /* Absolute value of bits 23-15. */
+         /* t8 - input byte. */
+         assign(t8,
+                unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
+         /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
+         assign(t9, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32, mkexpr(t8)),
+                          mkU32(0x00000080)));
+         /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
+         assign(t10, unop(Iop_32to1,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0x00800000)),
+                                mkU8(23))));
+         /* t3 holds abs(t8). */
+         assign(t11, IRExpr_ITE(mkexpr(t9),
+                                mkU8(0x7F),
+                                IRExpr_ITE(mkexpr(t10),
+                                           binop(Iop_Add8,
+                                                 unop(Iop_Not8,
+                                                       mkexpr(t8)),
+                                                 mkU8(0x1)),
+                                           mkexpr(t8))));
+
+         /* Absolute value of bits 31-24. */
+         /* t12 - input byte. */
+         assign(t12,
+                unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
+         /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
+         assign(t13, binop(Iop_CmpEQ32,
+                           unop(Iop_8Uto32, mkexpr(t12)),
+                           mkU32(0x00000080)));
+         /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
+         assign(t14, unop(Iop_32to1,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0x80000000)),
+                                mkU8(31))));
+         /* t15 holds abs(t12). */
+         assign(t15, IRExpr_ITE(mkexpr(t13),
+                                mkU8(0x7F),
+                                IRExpr_ITE(mkexpr(t14),
+                                           binop(Iop_Add8,
+                                                 unop(Iop_Not8,
+                                                       mkexpr(t12)),
+                                                 mkU8(0x1)),
+                                           mkexpr(t12))));
+
+         /* t16 holds !0 if any of input bytes is 0x80 or 0
+            otherwise. */
+         assign(t16,
+                binop(Iop_Or32,
+                      binop(Iop_Or32,
+                            binop(Iop_Or32,
+                                  unop(Iop_1Sto32, mkexpr(t13)),
+                                  unop(Iop_1Sto32, mkexpr(t9))),
+                            unop(Iop_1Sto32, mkexpr(t5))),
+                      unop(Iop_1Sto32, mkexpr(t1))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t16),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000))));
+
+         /* t17 = t15|t11|t7|t3 */
+         assign(t17,
+                binop(Iop_16HLto32,
+                      binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
+                      binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
+
+         putIReg(rd, mkexpr(t17));
+         break;
+      }
+
+      case 0x2: {  /* REPL.QB */
+         DIP("repl.qb r%u, %u", rd, dsp_imm);
+         vassert(!mode64);
+
+         putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
+                           (dsp_imm << 8) | (dsp_imm)));
+         break;
+      }
+
+      case 0x3: {  /* REPLV.QB */
+         DIP("replv.qb r%u, r%u", rd, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I8);
+
+         assign(t0, unop(Iop_32to8,
+                         binop(Iop_And32, getIReg(rt), mkU32(0xff))));
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
+                       binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
+         break;
+      }
+
+      case 0x4: {  /* PRECEQU.PH.QBL */
+         DIP("precequ.ph.qbl r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0xff000000)),
+                                 mkU8(1)),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x00ff0000)),
+                                 mkU8(9))));
+         break;
+      }
+
+      case 0x5: {  /* PRECEQU.PH.QBR */
+         DIP("precequ.ph.qbr r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shl32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x0000ff00)),
+                                 mkU8(15)),
+                           binop(Iop_Shl32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x000000ff)),
+                                 mkU8(7))));
+         break;
+      }
+
+      case 0x6: {  /* PRECEQU.PH.QBLA */
+         DIP("precequ.ph.qbla r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0xff000000)),
+                                 mkU8(1)),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x0000ff00)),
+                                 mkU8(1))));
+         break;
+      }
+
+      case 0x7: {  /* PRECEQU.PH.QBRA */
+         DIP("precequ.ph.qbra r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shl32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x00ff0000)),
+                                 mkU8(7)),
+                           binop(Iop_Shl32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x000000ff)),
+                                 mkU8(7))));
+         break;
+      }
+
+      case 0x9: {  /* ABSQ_S.PH */
+         DIP("absq_s.ph r%u, r%u", rd, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I16);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I16);
+         t4 = newTemp(Ity_I16);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I16);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         /* t0 holds lower 16 bits of value in rt. */
+         assign(t0, unop(Iop_32to16, getIReg(rt)));
+         /* t1 holds 1 if t0 is equal to 0x8000. */
+         assign(t1, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32, mkexpr(t0)),
+                          mkU32(0x00008000)));
+         /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
+         assign(t2, unop(Iop_32to1,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     getIReg(rt),
+                                     mkU32(0x00008000)),
+                               mkU8(15))));
+         /* t3 holds abs(t0). */
+         assign(t3, IRExpr_ITE(mkexpr(t1),
+                               mkU16(0x7FFF),
+                               IRExpr_ITE(mkexpr(t2),
+                                          binop(Iop_Add16,
+                                                unop(Iop_Not16,
+                                                      mkexpr(t0)),
+                                                mkU16(0x1)),
+                                          mkexpr(t0))));
+
+         /* t4 holds lower 16 bits of value in rt. */
+         assign(t4, unop(Iop_32HIto16, getIReg(rt)));
+         /* t5 holds 1 if t4 is equal to 0x8000. */
+         assign(t5, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32, mkexpr(t4)),
+                          mkU32(0x00008000)));
+         /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
+         assign(t6, unop(Iop_32to1,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     getIReg(rt),
+                                     mkU32(0x80000000)),
+                               mkU8(31))));
+         /* t7 holds abs(t4). */
+         assign(t7, IRExpr_ITE(mkexpr(t5),
+                               mkU16(0x7FFF),
+                               IRExpr_ITE(mkexpr(t6),
+                                          binop(Iop_Add16,
+                                                unop(Iop_Not16,
+                                                      mkexpr(t4)),
+                                                mkU16(0x1)),
+                                          mkexpr(t4))));
+         /* If any of the two input halfwords is equal 0x8000,
+            set bit 20 in DSPControl register. */
+         assign(t8, binop(Iop_Or32,
+                          unop(Iop_1Sto32, mkexpr(t5)),
+                          unop(Iop_1Sto32, mkexpr(t1))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t8),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000))));
+
+         /* t9 = t7|t3 */
+         assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
+
+         putIReg(rd, mkexpr(t9));
+         break;
+      }
+
+      case 0xA: {  /* REPL.PH */
+         DIP("repl.ph r%u, %u", rd, dsp_imm);
+         vassert(!mode64);
+         UShort immediate = extend_s_10to16(dsp_imm);
+
+         putIReg(rd, mkU32(immediate << 16 | immediate));
+         break;
+      }
+
+      case 0xB: {  /* REPLV.PH */
+         DIP("replv.ph r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, getIReg(rt)),
+                           unop(Iop_32to16, getIReg(rt))));
+         break;
+      }
+
+      case 0xC: {  /* PRECEQ.W.PHL */
+         DIP("preceq.w.phl r%u, r%u", rd, rt);
+         vassert(!mode64);
+         putIReg(rd, binop(Iop_And32,
+                           getIReg(rt),
+                           mkU32(0xffff0000)));
+         break;
+      }
+
+      case 0xD: {  /* PRECEQ.W.PHR */
+         DIP("preceq.w.phr r%u, r%u", rd, rt);
+         vassert(!mode64);
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, getIReg(rt)),
+                           mkU16(0x0)));
+         break;
+      }
+
+      case 0x11: {  /* ABSQ_S.W */
+         DIP("absq_s.w r%u, r%u", rd, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I1);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+
+         assign(t0,
+                binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t0),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
+
+         assign(t2, IRExpr_ITE(mkexpr(t0),
+                               mkU32(0x7FFFFFFF),
+                               IRExpr_ITE(mkexpr(t1),
+                                          binop(Iop_Add32,
+                                                unop(Iop_Not32,
+                                                      getIReg(rt)),
+                                                mkU32(0x1)),
+                                          getIReg(rt))));
+         putIReg(rd, mkexpr(t2));
+         break;
+      }
+
+      case 0x1B: {  /* BITREV */
+         DIP("bitrev r%u, r%u", rd, rt);
+         vassert(!mode64);
+         /* 32bit reversal as seen on Bit Twiddling Hacks site
+            http://graphics.stanford.edu/~seander/bithacks.html
+            section ReverseParallel */
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_Or32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0xaaaaaaaa)),
+                                mkU8(0x1)),
+                          binop(Iop_Shl32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0x55555555)),
+                                mkU8(0x1))));
+         assign(t2, binop(Iop_Or32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t1),
+                                      mkU32(0xcccccccc)),
+                                mkU8(0x2)),
+                          binop(Iop_Shl32,
+                                binop(Iop_And32,
+                                      mkexpr(t1),
+                                      mkU32(0x33333333)),
+                                mkU8(0x2))));
+         assign(t3, binop(Iop_Or32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0xf0f0f0f0)),
+                                mkU8(0x4)),
+                          binop(Iop_Shl32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0x0f0f0f0f)),
+                                mkU8(0x4))));
+         assign(t4, binop(Iop_Or32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t3),
+                                      mkU32(0xff00ff00)),
+                                mkU8(0x8)),
+                          binop(Iop_Shl32,
+                                binop(Iop_And32,
+                                      mkexpr(t3),
+                                      mkU32(0x00ff00ff)),
+                                mkU8(0x8))));
+         assign(t5, binop(Iop_Or32,
+                          binop(Iop_Shr32,
+                                mkexpr(t4),
+                                mkU8(0x10)),
+                          binop(Iop_Shl32,
+                                mkexpr(t4),
+                                mkU8(0x10))));
+         putIReg(rd, binop(Iop_Shr32,
+                           mkexpr(t5),
+                           mkU8(16)));
+         break;
+      }
+
+      case 0x1C: {  /* PRECEU.PH.QBL */
+         DIP("preceu.ph.qbl r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0xff000000)),
+                                 mkU8(8)),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x00ff0000)),
+                                 mkU8(16))));
+         break;
+      }
+
+      case 0x1E: {  /* PRECEU.PH.QBLA */
+         DIP("preceu.ph.qbla r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0xff000000)),
+                                 mkU8(8)),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x0000ff00)),
+                                 mkU8(8))));
+         break;
+      }
+
+      case 0x1D: {  /* PRECEU.PH.QBR */
+         DIP("preceu.ph.qbr r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Shl32,
+                                 binop(Iop_And32,
+                                       getIReg(rt),
+                                       mkU32(0x0000ff00)),
+                                 mkU8(8)),
+                           binop(Iop_And32,
+                                 getIReg(rt),
+                                 mkU32(0x000000ff))));
+         break;
+      }
+
+      case 0x1F: {  /* PRECEU.PH.QBRA */
+         DIP("preceu.ph.qbra r%u, r%u", rd, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_And32,
+                                 getIReg(rt),
+                                 mkU32(0x00ff0000)),
+                           binop(Iop_And32,
+                                 getIReg(rt),
+                                 mkU32(0x000000ff))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_EXTR_W( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
+              t15, t16, t17;
+   UInt   rs, rt, rd, sa, ac, rddsp_mask,
+          wrdsp_mask, shift;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+   ac = get_acNo(cins);
+   rddsp_mask = get_rddspMask(cins);
+   wrdsp_mask = get_wrdspMask(cins);
+   shift = get_shift(cins);
+
+   switch (sa) {
+      case 0x0: {  /* EXTR.W */
+         DIP("extr.w r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+
+         if (0 == rs) {
+            assign(t1, mkexpr(t0));
+         } else {
+            assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+         }
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least sifgnificant bit of the shifted value
+            from acc. */
+         if (0 == rs) {
+            assign(t8, mkU64(0x0ULL));
+         } else {
+            assign(t8, binop(Iop_And64,
+                             binop(Iop_Shr64,
+                                   mkexpr(t0),
+                                   mkU8(rs - 1)),
+                             mkU64(0x1ULL)));
+         }
+
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         if (0 == rs) {
+            putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
+         } else {
+            putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
+         }
+
+         break;
+      }
+
+      case 0x1: {  /* EXTRV.W */
+         DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+         t15 = newTemp(Ity_I8);
+
+         assign(t15, unop(Iop_32to8,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0x1f))));
+         assign(t0, getAcc(ac));
+         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      unop(Iop_8Uto32,
+                                           mkexpr(t15)),
+                                      mkU32(0)),
+                                unop(Iop_64to32, mkexpr(t0)),
+                                unop(Iop_64to32, mkexpr(t1))));
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least sifgnificant bit of the shifted value
+            from acc. */
+         assign(t8,
+                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                 unop(Iop_8Uto32,
+                                      mkexpr(t15)),
+                                 mkU32(0)),
+                           mkU64(0x0ULL),
+                           binop(Iop_And64,
+                                 binop(Iop_Shr64,
+                                       mkexpr(t0),
+                                       unop(Iop_32to8,
+                                            binop(Iop_Sub32,
+                                                  unop(Iop_8Uto32,
+                                                        mkexpr(t15)),
+                                                  mkU32(1)))),
+                                 mkU64(0x1ULL))));
+
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         break;
+      }
+
+      case 0x2: {  /* EXTP */
+         DIP("extp r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+         /* Extract pos field of DSPControl register. */
+         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+
+         /* Check if (pos - size) >= 0 [size <= pos]
+            if (pos < size)
+               put 1 to EFI field of DSPControl register
+            else
+               extract bits from acc and put 0 to EFI field of
+               DSPCtrl */
+         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffbfff)),
+                                        mkU32(0x4000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xffffbfff))));
+
+         /* If pos <= 31, shift right the value from the acc
+            (pos-size) times and take (size+1) bits from the least
+            significant positions. Otherwise, shift left the value
+            (63-pos) times, take (size+1) bits from the most
+            significant positions and shift right (31-size) times.*/
+         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkexpr(t1), mkU32(rs))),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkU32(63), mkexpr(t1)))));
+
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Shr64,
+                                     mkexpr(t0), mkexpr(t4)),
+                               binop(Iop_Shl64,
+                                     mkexpr(t0), mkexpr(t4))));
+
+         /* t6 holds a mask for bit extraction */
+         assign(t6,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_Not64,
+                                binop(Iop_Shl64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      mkU8(rs + 1))),
+                           unop(Iop_Not64,
+                                binop(Iop_Shr64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      mkU8(rs + 1)))));
+
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               unop(Iop_64to32,
+                                    binop(Iop_And64,
+                                          mkexpr(t5),
+                                          mkexpr(t6))),
+                               binop(Iop_Shr32,
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_And64,
+                                                mkexpr(t5),
+                                                mkexpr(t6))),
+                                     mkU8(31 - rs))));
+
+         putIReg(rt, mkexpr(t7));
+         break;
+      }
+
+      case 0x3: {  /* EXTPV */
+         DIP("extpv r%u, ac%u, r%u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
+         assign(t0, getAcc(ac));
+         /* Extract pos field of DSPControl register. */
+         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+
+         /* Check if (pos - size) >= 0 [size <= pos]
+            if (pos < size)
+               put 1 to EFI field of DSPControl register
+            else
+               extract bits from acc and put 0 to EFI field of
+               DSPCtrl */
+         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffbfff)),
+                                        mkU32(0x4000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xffffbfff))));
+
+         /* If pos <= 31, shift right the value from the acc
+            (pos-size) times and take (size+1) bits from the least
+            significant positions. Otherwise, shift left the value
+            (63-pos) times, take (size+1) bits from the most
+            significant positions and shift right (31-size)
+            times. */
+         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkexpr(t1), mkexpr(t8))),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkU32(63), mkexpr(t1)))));
+
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Shr64,
+                                     mkexpr(t0), mkexpr(t4)),
+                               binop(Iop_Shl64,
+                                     mkexpr(t0), mkexpr(t4))));
+
+         /* t6 holds a mask for bit extraction. */
+         assign(t6,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_Not64,
+                                binop(Iop_Shl64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      unop(Iop_32to8,
+                                           binop(Iop_Add32,
+                                                 mkexpr(t8),
+                                                 mkU32(1))))),
+                           unop(Iop_Not64,
+                                binop(Iop_Shr64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      unop(Iop_32to8,
+                                           binop(Iop_Add32,
+                                                 mkexpr(t8),
+                                                 mkU32(1)))))));
+
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               unop(Iop_64to32,
+                                    binop(Iop_And64,
+                                          mkexpr(t5),
+                                          mkexpr(t6))),
+                               binop(Iop_Shr32,
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_And64,
+                                                mkexpr(t5),
+                                                mkexpr(t6))),
+                                     unop(Iop_32to8,
+                                          binop(Iop_Sub32,
+                                                mkU32(31),
+                                                mkexpr(t8))))));
+
+         putIReg(rt, mkexpr(t7));
+         break;
+      }
+
+      case 0x4: {  /* EXTR_R.W */
+         DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+         t15 = newTemp(Ity_I64);
+         t16 = newTemp(Ity_I1);
+
+         assign(t0, getAcc(ac));
+         assign(t16, binop(Iop_CmpEQ32,
+                           mkU32(rs),
+                           mkU32(0)));
+         assign(t1, IRExpr_ITE(mkexpr(t16),
+                               mkexpr(t0),
+                               binop(Iop_Sar64,
+                                     mkexpr(t0),
+                                     mkU8(rs))));
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least significant bit of the shifted value
+            from acc. */
+         assign(t15, binop(Iop_Shr64,
+                           mkexpr(t0),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      binop(Iop_And32,
+                                            mkU32(rs),
+                                            mkU32(0x1f)),
+                                      mkU32(1)))));
+
+         assign(t8,
+                IRExpr_ITE(mkexpr(t16),
+                           mkU64(0x0ULL),
+                           binop(Iop_And64,
+                                 mkexpr(t15),
+                                 mkU64(0x0000000000000001ULL))));
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+         putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         break;
+      }
+
+      case 0x5: {  /* EXTRV_R.W */
+         DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+         t15 = newTemp(Ity_I8);
+
+         assign(t15, unop(Iop_32to8,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0x1f))));
+         assign(t0, getAcc(ac));
+         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least sifgnificant bit of the shifted value
+            from acc. */
+         assign(t8,
+                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                 unop(Iop_8Uto32,
+                                      mkexpr(t15)),
+                                 mkU32(0)),
+                           mkU64(0x0ULL),
+                           binop(Iop_And64,
+                                 binop(Iop_Shr64,
+                                       mkexpr(t0),
+                                       unop(Iop_32to8,
+                                            binop(Iop_Sub32,
+                                                  unop(Iop_8Uto32,
+                                                        mkexpr(t15)),
+                                                  mkU32(1)))),
+                                 mkU64(0x1ULL))));
+
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+         /* Put rounded value in destination register. */
+         putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         break;
+      }
+
+      case 0x6: {  /* EXTR_RS.W */
+         DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+         t16 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+
+         if (0 == rs) {
+            assign(t1, mkexpr(t0));
+         } else {
+            assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+         }
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least sifgnificant bit of the shifted value
+            from acc. */
+         if (0 == rs) {
+            assign(t8, mkU64(0x0ULL));
+         } else {
+            assign(t8, binop(Iop_And64,
+                             binop(Iop_Shr64,
+                                   mkexpr(t0),
+                                   mkU8(rs - 1)),
+                             mkU64(0x1ULL)));
+         }
+
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         assign(t16, binop(Iop_And32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0x80000000)));
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t14),
+                                      mkU32(0)),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 mkexpr(t16),
+                                                 mkU32(0)),
+                                           mkU32(0x7fffffff),
+                                           mkU32(0x80000000)),
+                                unop(Iop_64to32, mkexpr(t9))));
+         break;
+      }
+
+      case 0x7: {  /* EXTRV_RS.W */
+         DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I32);
+         t15 = newTemp(Ity_I32);
+         t16 = newTemp(Ity_I32);
+         t17 = newTemp(Ity_I1);
+
+         assign(t15, binop(Iop_And32,
+                           getIReg(rs),
+                           mkU32(0x1f)));
+         assign(t17, binop(Iop_CmpEQ32,
+                           mkexpr(t15),
+                           mkU32(0)));
+         assign(t0, getAcc(ac));
+         assign(t1, IRExpr_ITE(mkexpr(t17),
+                               mkexpr(t0),
+                               binop(Iop_Sar64,
+                                     mkexpr(t0),
+                                     unop(Iop_32to8,
+                                          mkexpr(t15)))));
+
+         /* Check if bits 63..31 of the result in t1 aren't 0. */
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0)));
+         /* Check if bits 63..31 of the result in t1 aren't
+            0x1ffffffff. */
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32,
+                               mkexpr(t1)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32,
+                                     mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU32(0x80000000)));
+         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
+            control register. */
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t3)),
+                                unop(Iop_1Sto32, mkexpr(t4))),
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32, mkexpr(t5)),
+                                unop(Iop_1Sto32, mkexpr(t6)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t7),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         /* If the last discarded bit is 1, there would be carry
+            when rounding, otherwise there wouldn't. We use that
+            fact and just add the value of the last discarded bit
+            to the least sifgnificant bit of the shifted value
+            from acc. */
+         assign(t8,
+                IRExpr_ITE(mkexpr(t17),
+                           mkU64(0x0ULL),
+                           binop(Iop_And64,
+                                 binop(Iop_Shr64,
+                                       mkexpr(t0),
+                                       unop(Iop_32to8,
+                                            binop(Iop_Sub32,
+                                                  mkexpr(t15),
+                                                  mkU32(1)))),
+                                 mkU64(0x1ULL))));
+
+         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+
+         /* Repeat previous steps for the rounded value. */
+         assign(t10, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0)));
+         assign(t11, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0)));
+
+         assign(t12, binop(Iop_CmpNE32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0xffffffff)));
+         assign(t13, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 unop(Iop_64to32,
+                                      mkexpr(t9)),
+                                 mkU32(0x80000000)),
+                           mkU32(0x80000000)));
+
+         assign(t14, binop(Iop_And32,
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t10)),
+                                 unop(Iop_1Sto32, mkexpr(t11))),
+                           binop(Iop_Or32,
+                                 unop(Iop_1Sto32, mkexpr(t12)),
+                                 unop(Iop_1Sto32, mkexpr(t13)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t14),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+
+         assign(t16, binop(Iop_And32,
+                           unop(Iop_64HIto32,
+                                mkexpr(t9)),
+                           mkU32(0x80000000)));
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t14),
+                                      mkU32(0)),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 mkexpr(t16),
+                                                 mkU32(0)),
+                                           mkU32(0x7fffffff),
+                                           mkU32(0x80000000)),
+                                unop(Iop_64to32, mkexpr(t9))));
+         break;
+      }
+
+      case 0xA: {  /* EXTPDP */
+         DIP("extpdp r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+         /* Extract pos field of DSPControl register. */
+         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+
+         /* Check if (pos - size) >= 0 [size <= pos]
+            if (pos < size)
+               put 1 to EFI field of DSPControl register
+            else
+               extract bits from acc and put 0 to EFI field of
+               DSPCtrl */
+         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
+
+         assign(t8, binop(Iop_Or32,
+                          binop(Iop_And32,
+                                getDSPControl(),
+                                mkU32(0xffffbfc0)),
+                          binop(Iop_And32,
+                                binop(Iop_Sub32,
+                                      binop(Iop_And32,
+                                            getDSPControl(),
+                                            mkU32(0x3f)),
+                                      mkU32(rs + 1)),
+                                mkU32(0x3f))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffbfff)),
+                                        mkU32(0x4000)),
+                                  mkexpr(t8)));
+
+         /* If pos <= 31, shift right the value from the acc
+            (pos-size) times and take (size+1) bits from the least
+            significant positions. Otherwise, shift left the value
+            (63-pos) times, take (size+1) bits from the most
+            significant positions and shift right (31-size) times.
+         */
+         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkexpr(t1), mkU32(rs))),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkU32(63), mkexpr(t1)))));
+
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Shr64,
+                                     mkexpr(t0), mkexpr(t4)),
+                               binop(Iop_Shl64,
+                                     mkexpr(t0), mkexpr(t4))));
+
+         /* t6 holds a mask for bit extraction. */
+         assign(t6,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_Not64,
+                                binop(Iop_Shl64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      mkU8(rs + 1))),
+                           unop(Iop_Not64,
+                                binop(Iop_Shr64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      mkU8(rs + 1)))));
+
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               unop(Iop_64to32,
+                                    binop(Iop_And64,
+                                          mkexpr(t5),
+                                          mkexpr(t6))),
+                               binop(Iop_Shr32,
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_And64,
+                                                mkexpr(t5),
+                                                mkexpr(t6))),
+                                     mkU8(31 - rs))));
+
+         putIReg(rt, mkexpr(t7));
+         break;
+      }
+
+      case 0xB: {  /* EXTPDPV */
+         DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
+         assign(t0, getAcc(ac));
+         /* Extract pos field of DSPControl register. */
+         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+
+         /* Check if (pos - size) >= 0 [size <= pos]
+            if (pos < size)
+               put 1 to EFI field of DSPControl register
+            else
+               extract bits from acc and put 0 to EFI field of
+               DSPCtrl */
+         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
+
+         assign(t9, binop(Iop_Or32,
+                          binop(Iop_And32,
+                                getDSPControl(),
+                                mkU32(0xffffbfc0)),
+                          binop(Iop_And32,
+                                binop(Iop_Sub32,
+                                      binop(Iop_And32,
+                                            getDSPControl(),
+                                            mkU32(0x3f)),
+                                      binop(Iop_Add32,
+                                            mkexpr(t8),
+                                            mkU32(0x1))),
+                                mkU32(0x3f))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffbfff)),
+                                        mkU32(0x4000)),
+                                  mkexpr(t9)));
+
+         /* If pos <= 31, shift right the value from the acc
+            (pos-size) times and take (size+1) bits from the least
+            significant positions. Otherwise, shift left the value
+            (63-pos) times, take (size+1) bits from the most
+            significant positions and shift right (31-size) times.
+         */
+         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkexpr(t1), mkexpr(t8))),
+                           unop(Iop_32to8,
+                                binop(Iop_Sub32,
+                                      mkU32(63), mkexpr(t1)))));
+
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Shr64,
+                                     mkexpr(t0), mkexpr(t4)),
+                               binop(Iop_Shl64,
+                                     mkexpr(t0), mkexpr(t4))));
+
+         /* t6 holds a mask for bit extraction. */
+         assign(t6,
+                IRExpr_ITE(mkexpr(t3),
+                           unop(Iop_Not64,
+                                binop(Iop_Shl64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      unop(Iop_32to8,
+                                           binop(Iop_Add32,
+                                                 mkexpr(t8),
+                                                 mkU32(1))))),
+                           unop(Iop_Not64,
+                                binop(Iop_Shr64,
+                                      mkU64(0xffffffffffffffffULL),
+                                      unop(Iop_32to8,
+                                           binop(Iop_Add32,
+                                                 mkexpr(t8),
+                                                 mkU32(1)))))));
+
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               unop(Iop_64to32,
+                                    binop(Iop_And64,
+                                          mkexpr(t5),
+                                          mkexpr(t6))),
+                               binop(Iop_Shr32,
+                                     unop(Iop_64HIto32,
+                                          binop(Iop_And64,
+                                                mkexpr(t5),
+                                                mkexpr(t6))),
+                                     unop(Iop_32to8,
+                                          binop(Iop_Sub32,
+                                                mkU32(31),
+                                                mkexpr(t8))))));
+
+         putIReg(rt, mkexpr(t7));
+         break;
+      }
+
+      case 0xE: {  /* EXTR_S.H */
+         DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+
+         assign(t2, binop(Iop_Or32,
+                          getDSPControl(), mkU32(0x00800000)));
+
+         assign(t9, binop(Iop_And32,
+                          unop(Iop_64to32,
+                               mkexpr(t1)),
+                          mkU32(0x80000000)));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t9),
+                                        binop(Iop_And32,
+                                              unop(Iop_64HIto32,
+                                                    mkexpr(t0)),
+                                              mkU32(0x80000000))),
+                                  mkexpr(t2),
+                                  getDSPControl()));
+
+         /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
+            1. subtract 0x7fff from t1
+            2. if the resulting number is positive (sign bit = 0)
+               and any of the other bits is 1, the value is > 0. */
+         assign(t3, binop(Iop_Sub64,
+                          mkexpr(t1),
+                          mkU64(0x0000000000007fffULL)));
+         assign(t4, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           binop(Iop_And32,
+                                                 unop(Iop_64HIto32,
+                                                       mkexpr(t3)),
+                                                 mkU32(0x7fffffff)))),
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           unop(Iop_64to32,
+                                                mkexpr(t3))))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t3)),
+                                           mkU32(0x80000000)),
+                                     mkU32(0)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkU32(0),
+                                        mkexpr(t4)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
+            1. subtract t1 from 0xffffffffffff8000
+            2. if the resulting number is positive (sign bit = 0)
+                and any of the other bits is 1, the value is > 0 */
+         assign(t6, binop(Iop_Sub64,
+                          mkU64(0xffffffffffff8000ULL),
+                          mkexpr(t1)));
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           binop(Iop_And32,
+                                                 unop(Iop_64HIto32,
+                                                       mkexpr(t6)),
+                                                 mkU32(0x7fffffff)))),
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           unop(Iop_64to32,
+                                                mkexpr(t6))))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t6)),
+                                           mkU32(0x80000000)),
+                                     mkU32(0)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkU32(0),
+                                        mkexpr(t7)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkU32(0),
+                                      mkexpr(t4)),
+                                mkU32(0x00007fff),
+                                IRExpr_ITE(binop(Iop_CmpNE32,
+                                                 mkU32(0),
+                                                 mkexpr(t7)),
+                                           mkU32(0xffff8000),
+                                           unop(Iop_64to32,
+                                                mkexpr(t1)))));
+         break;
+      }
+
+      case 0xF: {  /* EXTRV_S.H */
+         DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Sar64,
+                          mkexpr(t0),
+                          unop(Iop_32to8,
+                               binop(Iop_And32,
+                                     getIReg(rs),
+                                     mkU32(0x1f)))));
+
+         assign(t2, binop(Iop_Or32,
+                          getDSPControl(), mkU32(0x00800000)));
+
+         assign(t9, binop(Iop_And32,
+                          unop(Iop_64to32,
+                               mkexpr(t1)),
+                          mkU32(0x80000000)));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t9),
+                                        binop(Iop_And32,
+                                              unop(Iop_64HIto32,
+                                                    mkexpr(t0)),
+                                              mkU32(0x80000000))),
+                                  mkexpr(t2),
+                                  getDSPControl()));
+
+         /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
+            1. subtract 0x7fff from t1
+            2. if the resulting number is positive (sign bit = 0)
+               and any of the other bits is 1, the value is > 0. */
+         assign(t3, binop(Iop_Sub64,
+                          mkexpr(t1),
+                          mkU64(0x0000000000007fffULL)));
+         assign(t4, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           binop(Iop_And32,
+                                                 unop(Iop_64HIto32,
+                                                       mkexpr(t3)),
+                                                 mkU32(0x7fffffff)))),
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           unop(Iop_64to32,
+                                                mkexpr(t3))))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t3)),
+                                           mkU32(0x80000000)),
+                                     mkU32(0)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkU32(0),
+                                        mkexpr(t4)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
+            1. subtract t1 from 0xffffffffffff8000
+            2. if the resulting number is positive (sign bit = 0)
+                and any of the other bits is 1, the value is > 0 */
+         assign(t6, binop(Iop_Sub64,
+                          mkU64(0xffffffffffff8000ULL),
+                          mkexpr(t1)));
+         assign(t7, binop(Iop_And32,
+                          binop(Iop_Or32,
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           binop(Iop_And32,
+                                                 unop(Iop_64HIto32,
+                                                       mkexpr(t6)),
+                                                 mkU32(0x7fffffff)))),
+                                unop(Iop_1Sto32,
+                                     binop(Iop_CmpNE32,
+                                           mkU32(0),
+                                           unop(Iop_64to32,
+                                                mkexpr(t6))))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t6)),
+                                           mkU32(0x80000000)),
+                                     mkU32(0)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkU32(0),
+                                        mkexpr(t7)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00800000)),
+                                  getDSPControl()));
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkU32(0),
+                                      mkexpr(t4)),
+                                mkU32(0x00007fff),
+                                IRExpr_ITE(binop(Iop_CmpNE32,
+                                                 mkU32(0),
+                                                 mkexpr(t7)),
+                                           mkU32(0xffff8000),
+                                           unop(Iop_64to32,
+                                                mkexpr(t1)))));
+         break;
+      }
+
+      case 0x12: {  /* RDDSP*/
+         DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask);
+         vassert(!mode64);
+
+         putIReg(rd, mkU32(0x0));
+
+         if ((rddsp_mask & 0x1) == 0x1) {
+            /* Read pos field (bits 5-0) of DSPControl register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0x0000003F))));
+         }
+
+         if ((rddsp_mask & 0x2) == 0x2) {
+            /* Read scount field (bits 12-7) of DSPControl
+               register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0x00001F80))));
+         }
+
+         if ((rddsp_mask & 0x4) == 0x4) {
+            /* Read C field (bit 13) of DSPControl register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0x00002000))));
+         }
+
+         if ((rddsp_mask & 0x8) == 0x8) {
+            /* Read outflag field (bit s 23-16) of DSPControl
+               register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0x00FF0000))));
+         }
+
+         if ((rddsp_mask & 0x10) == 0x10) {
+            /* Read ccond field (bits 31-24) of DSPControl
+               register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0xFF000000))));
+         }
+
+         if ((rddsp_mask & 0x20) == 0x20) {
+            /* Read EFI field (bit 14) of DSPControl register. */
+            putIReg(rd, binop(Iop_Or32,
+                              getIReg(rd),
+                              binop(Iop_And32,
+                                    getDSPControl(),
+                                    mkU32(0x00004000))));
+         }
+
+         if ((rddsp_mask & 0x3f) == 0x3f) {
+            /* Read all fields of DSPControl register. */
+            putIReg(rd, getDSPControl());
+         }
+
+         break;
+      }
+
+      case 0x13: {  /* WRDSP */
+         DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask);
+         vassert(!mode64);
+
+         if ((wrdsp_mask & 0x3f) == 0x3f) {
+            /* If mips64 put all fields of rs, except bit 15 and bit
+               6, to DSPControl register, otherwise put all except
+               bits 15, 6 and bits 31..28. */
+            putDSPControl(mode64 ?
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0xffff7fbf)) :
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0x0fff7fbf)));
+         } else {
+            if ((wrdsp_mask & 0x1) == 0x1) {
+               /* Put bits 5-0 of rs to DSPControl register pos
+                  field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0xFFFF7F40)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mkU32(0x0000003F))));
+            }
+
+            if ((wrdsp_mask & 0x2) == 0x2) {
+               /* Put bits 12-7 of rs to DSPControl scount field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0xFFFFE03F)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mkU32(0x00001F80))));
+            }
+
+            if ((wrdsp_mask & 0x4) == 0x4) {
+               /* Put bit 13 of rs to DSPControl register C
+                  field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0xFFFF5FBF)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mkU32(0x00002000))));
+            }
+
+            if ((wrdsp_mask & 0x8) == 0x8) {
+               /* Put bits 23-16 of rs to DSPControl reg outflag
+                  field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0xFF007FBF)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mkU32(0x00FF0000))));
+            }
+
+            if ((wrdsp_mask & 0x10) == 0x10) {
+               /* Put bits 31-24 of rs to DSPControl reg ccond
+                  field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0x00FF7FBF)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mode64 ? mkU32(0xFF000000)
+                                         : mkU32(0x0F000000))
+                                  )
+                            );
+            }
+
+            if ((wrdsp_mask & 0x20) == 0x20) {
+               /* Put bit 14 of rs to DSPControl register EFI
+                  field. */
+               putDSPControl(binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         getDSPControl(),
+                                         mkU32(0xFFFF3FBF)),
+                                   binop(Iop_And32,
+                                         getIReg(rs),
+                                         mkU32(0x00004000))));
+            }
+         }
+
+         break;
+      }
+
+      case 0x1A: {  /* SHILO */
+         DIP("shilo ac%u, %u", ac, shift);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+
+         putAcc(ac, mkexpr(t0));
+
+         if (0x20 == (shift & 0x3f)) {
+            putAcc(ac, binop(Iop_32HLto64,
+                             unop(Iop_64to32, mkexpr(t0)),
+                             mkU32(0x0)));
+         } else if (0x20 == (shift & 0x20)) {
+            assign(t1, binop(Iop_Shl64,
+                             mkexpr(t0),
+                             unop(Iop_32to8,
+                                  binop(Iop_Add32,
+                                        unop(Iop_Not32,
+                                             mkU32(shift)),
+                                        mkU32(0x1)))));
+
+            putAcc(ac, mkexpr(t1));
+         } else {
+            assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
+
+            putAcc(ac, mkexpr(t1));
+         }
+
+         break;
+      }
+
+      case 0x1B: {  /* SHILOV */
+         DIP("shilov ac%u, r%u", ac, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+         assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
+         assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
+         assign(t3, binop(Iop_Shl64,
+                          mkexpr(t0),
+                          unop(Iop_32to8,
+                               binop(Iop_Add32,
+                                     unop(Iop_Not32,
+                                          mkexpr(t1)),
+                                     mkU32(0x1)))));
+         assign(t4, binop(Iop_Shr64,
+                          mkexpr(t0),
+                          unop(Iop_32to8,
+                               mkexpr(t1))));
+
+         putAcc(ac,
+                IRExpr_ITE(mkexpr(t2),
+                           binop(Iop_32HLto64,
+                                 unop(Iop_64to32, mkexpr(t0)),
+                                 mkU32(0x0)),
+                           IRExpr_ITE(binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  mkexpr(t1),
+                                                  mkU32(0x20)),
+                                            mkU32(0x20)),
+                                      mkexpr(t3),
+                                      mkexpr(t4))));
+         break;
+      }
+
+      case 0x1F: {  /* MTHLIP */
+         DIP("mthlip r%u, ac%u", rs, ac);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+
+         assign(t0, getAcc(ac));
+         putAcc(ac, binop(Iop_32HLto64,
+                          unop(Iop_64to32, mkexpr(t0)),
+                          getIReg(rs)));
+         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
+                                        mkU32(32),
+                                        mkexpr(t1)),
+                                  binop(Iop_Or32,
+                                        binop(Iop_Sub32,
+                                              mkexpr(t1),
+                                              mkU32(32)),
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffffc0))),
+                                  binop(Iop_Or32,
+                                        binop(Iop_Add32,
+                                              mkexpr(t1),
+                                              mkU32(32)),
+                                        binop(Iop_And32,
+                                              getDSPControl(),
+                                              mkU32(0xffffffc0)))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_LX( UInt cins )
+{
+   IRTemp t0;
+   UInt   rs, rt, rd, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x0: {  /* LWX */
+         DIP("lwx r%u, r%u(r%u)", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+
+         putIReg(rd, load(Ity_I32, mkexpr(t0)));
+         break;
+      }
+
+      case 0x4: {  /* LHX */
+         DIP("lhx r%u, r%u(r%u)", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+
+         putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
+         break;
+      }
+
+      case 0x6: {  /* LBUX */
+         DIP("lbux r%u, r%u(r%u)", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+
+         putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_INSV( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t6, t7, t8;
+   UInt   rs, rt, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x0: {  /* INSV */
+         DIP("insv r%u, r%u", rt, rs);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         /* t0 <- pos field of DSPControl register. */
+         assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+         /* t1 <- scount field of DSPControl register. */
+         assign(t1, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getDSPControl(),
+                                mkU32(0x1f80)),
+                          mkU8(7)));
+
+         assign(t2, unop(Iop_32to8,
+                         binop(Iop_Add32,
+                               mkexpr(t1),
+                               mkexpr(t0))));
+
+         /* 32-(pos+size) most significant bits of rt. */
+         assign(t6, binop(Iop_Shl32,
+                          binop(Iop_Shr32,
+                                getIReg(rt),
+                                mkexpr(t2)),
+                          mkexpr(t2)));
+
+         assign(t3, unop(Iop_32to8,
+                         binop(Iop_Sub32,
+                               mkU32(32),
+                               mkexpr(t0))));
+         /* Pos least significant bits of rt. */
+         assign(t7, binop(Iop_Shr32,
+                          binop(Iop_Shl32,
+                                getIReg(rt),
+                                mkexpr(t3)),
+                          mkexpr(t3)));
+
+         /* Size least significant bits of rs,
+            shifted to appropriate position. */
+         assign(t8, binop(Iop_Shl32,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                unop(Iop_Not32,
+                                     binop(Iop_Shl32,
+                                           mkU32(0xffffffff),
+                                           unop(Iop_32to8,
+                                                mkexpr(t1))))),
+                          unop(Iop_32to8,
+                               mkexpr(t0))));
+
+         putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      mkexpr(t0),
+                                      mkU32(0)),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 mkexpr(t1),
+                                                 mkU32(32)),
+                                           getIReg(rs),
+                                           binop(Iop_Or32,
+                                                 mkexpr(t6),
+                                                 mkexpr(t8))),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 unop(Iop_8Uto32,
+                                                       mkexpr(t2)),
+                                                 mkU32(32)),
+                                           binop(Iop_Or32,
+                                                 mkexpr(t7),
+                                                 mkexpr(t8)),
+                                           binop(Iop_Or32,
+                                                 binop(Iop_Or32,
+                                                       mkexpr(t6),
+                                                       mkexpr(t7)),
+                                                 mkexpr(t8)))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_ADDU_QB( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
+   UInt   rs, rt, rd, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x00: {  /* ADDU.QB */
+         DIP("addu.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I32);
+
+         /* Add rightmost bytes of rs and rt. */
+         assign(t0,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t1 will be 1 if there is overflow, 0 otherwise. */
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t2,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t3 will be 1 if there is overflow, 0 otherwise. */
+         assign(t3, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t2),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t4,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t5 will be 1 if there is overflow, 0 otherwise. */
+         assign(t5, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t4),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t6,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t7 will be 1 if there is overflow, 0 otherwise. */
+         assign(t7, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t6),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         assign(t8,
+                binop(Iop_Or32,
+                      binop(Iop_Or32,
+                            binop(Iop_Or32,
+                                  unop(Iop_1Sto32, mkexpr(t7)),
+                                  unop(Iop_1Sto32,  mkexpr(t5))),
+                            unop(Iop_1Sto32, mkexpr(t3))),
+                      unop(Iop_1Sto32, mkexpr(t1))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t8),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           binop(Iop_8HLto16,
+                                 unop(Iop_32to8, mkexpr(t6)),
+                                 unop(Iop_32to8, mkexpr(t4))),
+                           binop(Iop_8HLto16,
+                                 unop(Iop_32to8, mkexpr(t2)),
+                                 unop(Iop_32to8, mkexpr(t0)))));
+         break;
+      }
+
+      case 0x1: {  /* SUBU.QB */
+         DIP("subu.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I32);
+
+         /* Subtract rightmost bytes of rs and rt. */
+         assign(t0,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t1 will be 1 if there is overflow, 0 otherwise. */
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Subtract bits 15-8 of rs and rt. */
+         assign(t2,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t3 will be 1 if there is overflow, 0 otherwise. */
+         assign(t3, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t2),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Subtract bits 15-8 of rs and rt. */
+         assign(t4,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t5 will be 1 if there is overflow, 0 otherwise. */
+         assign(t5, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t4),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         /* Subtract bits 15-8 of rs and rt. */
+         assign(t6,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t7 will be 1 if there is overflow, 0 otherwise. */
+         assign(t7, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t6),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+
+         assign(t8, binop(Iop_Or32,
+                          binop(Iop_Or32,
+                                binop(Iop_Or32,
+                                      unop(Iop_1Sto32, mkexpr(t7)),
+                                      unop(Iop_1Sto32, mkexpr(t5))),
+                                unop(Iop_1Sto32, mkexpr(t3))),
+                          unop(Iop_1Sto32, mkexpr(t1))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t8),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           binop(Iop_8HLto16,
+                                 unop(Iop_32to8, mkexpr(t6)),
+                                 unop(Iop_32to8, mkexpr(t4))),
+                           binop(Iop_8HLto16,
+                                 unop(Iop_32to8, mkexpr(t2)),
+                                 unop(Iop_32to8, mkexpr(t0)))));
+         break;
+      }
+
+      case 0x04: {  /* ADDU_S.QB */
+         DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I8);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I8);
+         t12 = newTemp(Ity_I32);
+
+         /* Add rightmost bytes of rs and rt. */
+         assign(t0,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t1 will be 1 if there is overflow, 0 otherwise. */
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         /* Saturate if necessary. */
+         assign(t2, IRExpr_ITE(mkexpr(t1),
+                               mkU8(0xff),
+                               unop(Iop_32to8, mkexpr(t0))));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t3,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* t4 will be 1 if there is overflow, 0 otherwise. */
+         assign(t4, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t3),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         /* Saturate if necessary. */
+         assign(t5, IRExpr_ITE(mkexpr(t4),
+                               mkU8(0xff),
+                               unop(Iop_32to8, mkexpr(t3))));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t6,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t7 will be 1 if there is overflow, 0 otherwise. */
+         assign(t7, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t6),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         /* Saturate if necessary. */
+         assign(t8, IRExpr_ITE(mkexpr(t7),
+                               mkU8(0xff),
+                               unop(Iop_32to8, mkexpr(t6))));
+
+         /* Add bits 15-8 of rs and rt. */
+         assign(t9,
+                binop(Iop_Add32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         /* t10 will be 1 if there is overflow, 0 otherwise. */
+         assign(t10, binop(Iop_CmpEQ32,
+                           binop(Iop_And32,
+                                 mkexpr(t9),
+                                 mkU32(0x00000100)),
+                           mkU32(0x00000100)));
+         /* Saturate if necessary. */
+         assign(t11, IRExpr_ITE(mkexpr(t10),
+                                mkU8(0xff),
+                                unop(Iop_32to8, mkexpr(t9))));
+
+         assign(t12,
+                binop(Iop_Or32,
+                      binop(Iop_Or32,
+                            binop(Iop_Or32,
+                                  unop(Iop_1Sto32, mkexpr(t10)),
+                                  unop(Iop_1Sto32, mkexpr(t7))),
+                            unop(Iop_1Sto32, mkexpr(t4))),
+                      unop(Iop_1Sto32, mkexpr(t1))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t12),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000))));
+
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
+                       binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
+         break;
+      }
+
+      case 0x05: {  /* SUBU_S.QB */
+         DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         /* Use C function to easily calculate the result
+            and write it in the register more conveniently
+            Underflow is checked using step by step subtraction. */
+         assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
+
+         /* Subtract each byte of rs and rt. */
+         assign(t6,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t7,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t8,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t9,
+                binop(Iop_Sub32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+
+         /* Put 1 to bit 20 in DSPControl if there is underflow
+            in either byte. */
+         assign(t2, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t6),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         assign(t3, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t7),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         assign(t4, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t8),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         assign(t5, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                mkexpr(t9),
+                                mkU32(0x00000100)),
+                          mkU32(0x00000100)));
+         putDSPControl(IRExpr_ITE(mkexpr(t5),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         putIReg(rd, mkexpr(t1));
+         break;
+      }
+
+      case 0x6: {  /* MULEU_S.PH.QBL */
+         DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+
+         assign(t0,
+                unop(Iop_64to32,
+                     binop(Iop_MullU32,
+                           unop(Iop_8Uto32,
+                                unop(Iop_16HIto8,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs)))),
+                           unop(Iop_16Uto32,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t1,
+                unop(Iop_64to32,
+                     binop(Iop_MullU32,
+                           unop(Iop_8Uto32,
+                                unop(Iop_16to8,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs)))),
+                           unop(Iop_16Uto32,
+                                unop(Iop_32to16, getIReg(rt))))));
+
+         assign(t2, binop(Iop_CmpNE32,
+                          mkU32(0x0),
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x03ff0000))));
+         assign(t3, binop(Iop_CmpNE32,
+                          mkU32(0x0),
+                          binop(Iop_And32,
+                                mkexpr(t1),
+                                mkU32(0x03ff0000))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x200000)),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x200000)),
+                                             getDSPControl())));
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       IRExpr_ITE(mkexpr(t2),
+                                  mkU16(0xffff),
+                                  unop(Iop_32to16, mkexpr(t0))),
+                       IRExpr_ITE(mkexpr(t3),
+                                  mkU16(0xffff),
+                                  unop(Iop_32to16, mkexpr(t1)))));
+         break;
+      }
+
+      case 0x7: {  /* MULEU_S.PH.QBR */
+         DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+
+         assign(t0, unop(Iop_64to32,
+                         binop(Iop_MullU32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_16HIto8,
+                                         unop(Iop_32to16,
+                                              getIReg(rs)))),
+                               unop(Iop_16Uto32,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t1, unop(Iop_64to32,
+                         binop(Iop_MullU32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_16to8,
+                                         unop(Iop_32to16,
+                                              getIReg(rs)))),
+                               unop(Iop_16Uto32,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+
+         assign(t2, binop(Iop_CmpNE32,
+                          mkU32(0x0),
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x03ff0000))));
+         assign(t3, binop(Iop_CmpNE32,
+                          mkU32(0x0),
+                          binop(Iop_And32,
+                                mkexpr(t1),
+                                mkU32(0x03ff0000))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x200000)),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x200000)),
+                                             getDSPControl())));
+         putIReg(rd, binop(Iop_16HLto32,
+                           IRExpr_ITE(mkexpr(t2),
+                                      mkU16(0xffff),
+                                      unop(Iop_32to16,
+                                           mkexpr(t0))),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU16(0xffff),
+                                      unop(Iop_32to16,
+                                           mkexpr(t1)))));
+         break;
+      }
+
+      case 0x08: {  /* ADDU.PH */
+         DIP("addu.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+
+         /* Add lower halves. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Detect overflow. */
+         assign(t1, binop(Iop_CmpLT32U,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, mkexpr(t0))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs)))));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Add higher halves. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Detect overflow. */
+         assign(t3, binop(Iop_CmpLT32U,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, mkexpr(t2))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16,
+                                    getIReg(rs)))));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t2)),
+                           unop(Iop_32to16, mkexpr(t0))));
+         break;
+      }
+
+      case 0x9: {  /* SUBU.PH */
+         DIP("subu.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+
+         /* Substract lower halves. */
+         assign(t0, binop(Iop_Sub32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Detect underflow. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x00010000)),
+                          mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Subtract higher halves. */
+         assign(t2, binop(Iop_Sub32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Detect underflow. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t2),
+                                mkU32(0x00010000)),
+                          mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t2)),
+                           unop(Iop_32to16, mkexpr(t0))));
+         break;
+      }
+
+      case 0xA: {  /* ADDQ.PH */
+         DIP("addq.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+
+         /* Add lower halves. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t6, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t0))),
+                          mkU32(0x1)));
+         /* Detect overflow. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t0),
+                                      mkU32(0x8000)),
+                                mkU8(15)),
+                          mkexpr(t6)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Add higher halves. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t7, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x1)));
+         /* Detect overflow. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0x00008000)),
+                                mkU8(15)),
+                          mkexpr(t7)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t2)),
+                           unop(Iop_32to16, mkexpr(t0))));
+         break;
+      }
+
+      case 0xB: {  /* SUBQ.PH */
+         DIP("subq.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+
+         /* Subtract lower halves. */
+         assign(t0, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t6, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t0))),
+                          mkU32(0x1)));
+         /* Compare the signs of input value and the result. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t0),
+                                      mkU32(0x8000)),
+                                mkU8(15)),
+                          mkexpr(t6)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Subtract higher halves. */
+         assign(t2, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t7, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x1)));
+         /* Compare the signs of input value and the result. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0x00008000)),
+                                mkU8(15)),
+                          mkexpr(t7)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t2)),
+                           unop(Iop_32to16, mkexpr(t0))));
+         break;
+      }
+
+      case 0xC: {  /* ADDU_S.PH */
+         DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+
+         /* Add lower halves. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Detect overflow. */
+         assign(t1, binop(Iop_CmpLT32U,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, mkexpr(t0))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs)))));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Add higher halves. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Detect overflow. */
+         assign(t3, binop(Iop_CmpLT32U,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, mkexpr(t2))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs)))));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU16(0xffff),
+                                      unop(Iop_32to16,
+                                           mkexpr(t2))),
+                           IRExpr_ITE(mkexpr(t1),
+                                      mkU16(0xffff),
+                                      unop(Iop_32to16,
+                                           mkexpr(t0)))));
+         break;
+      }
+
+      case 0xD: {  /* SUBU_S.PH */
+         DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+
+         /* Subtract lower halves. */
+         assign(t0, binop(Iop_Sub32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Detect underflow. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0), mkU32(0x00010000)),
+                          mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         /* Subtract higher halves. */
+         assign(t2, binop(Iop_Sub32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Detect underflow. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t2), mkU32(0x00010000)),
+                          mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       IRExpr_ITE(mkexpr(t3),
+                                  mkU16(0x0000),
+                                  unop(Iop_32to16, mkexpr(t2))),
+                       IRExpr_ITE(mkexpr(t1),
+                                  mkU16(0x0000),
+                                  unop(Iop_32to16, mkexpr(t0)))));
+         break;
+      }
+
+      case 0xE: {  /* ADDQ_S.PH */
+         DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I16);
+         t5 = newTemp(Ity_I16);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+
+         /* Add lower halves. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t6, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t0))),
+                          mkU32(0x1)));
+         /* Detect overflow. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t0),
+                                      mkU32(0x8000)),
+                                mkU8(15)),
+                          mkexpr(t6)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         /* Saturate if needed. */
+         assign(t4, IRExpr_ITE(mkexpr(t1),
+                               IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                mkexpr(t6),
+                                                mkU32(0x0)),
+                                          mkU16(0x7fff),
+                                          mkU16(0x8000)),
+                               unop(Iop_32to16, mkexpr(t0))));
+
+         /* Add higher halves. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t7, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x1)));
+         /* Detect overflow. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0x00008000)),
+                                mkU8(15)),
+                          mkexpr(t7)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         /* Saturate if needed. */
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                mkexpr(t7),
+                                                mkU32(0x0)),
+                                          mkU16(0x7fff),
+                                          mkU16(0x8000)),
+                               unop(Iop_32to16, mkexpr(t2))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
+         break;
+      }
+
+      case 0xF: {  /* SUBQ_S.PH */
+         DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I16);
+         t5 = newTemp(Ity_I16);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+
+         /* Subtract lower halves. */
+         assign(t0, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t6, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t0))),
+                          mkU32(0x1)));
+         /* Detect overflow or underflow. */
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t0),
+                                      mkU32(0x8000)),
+                                mkU8(15)),
+                          mkexpr(t6)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         /* Saturate if needed. */
+         assign(t4, IRExpr_ITE(mkexpr(t1),
+                               IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                mkexpr(t6),
+                                                mkU32(0x0)),
+                                          mkU16(0x7fff),
+                                          mkU16(0x8000)),
+                               unop(Iop_32to16, mkexpr(t0))));
+
+         /* Subtract higher halves. */
+         assign(t2, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Bit 16 of the result. */
+         assign(t7, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x1)));
+         /* Detect overflow or underflow. */
+         assign(t3, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      mkexpr(t2),
+                                      mkU32(0x00008000)),
+                                mkU8(15)),
+                          mkexpr(t7)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         /* Saturate if needed. */
+         assign(t5, IRExpr_ITE(mkexpr(t3),
+                               IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                mkexpr(t7),
+                                                mkU32(0x0)),
+                                          mkU16(0x7fff),
+                                          mkU16(0x8000)),
+                               unop(Iop_32to16, mkexpr(t2))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
+         break;
+      }
+
+      case 0x10: {  /* ADDSC */
+         DIP("addsc r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+
+         /* The carry bit result out of the addition operation is
+            written to bit 13(the c field) of the DSPControl reg. */
+         assign(t0, binop(Iop_Add64,
+                          unop(Iop_32Uto64, getIReg(rs)),
+                          unop(Iop_32Uto64, getIReg(rt))));
+
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t0)),
+                                mkU32(0x1)),
+                          mkU32(0x1)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x2000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xffffdfff))));
+
+         putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
+         break;
+      }
+
+      case 0x11: {  /* ADDWC */
+         DIP("addwc r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I1);
+
+         /* Get carry bit from DSPControl register. */
+         assign(t0, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getDSPControl(),
+                                mkU32(0x2000)),
+                          mkU8(0xd)));
+         assign(t1, binop(Iop_Add64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64,
+                               binop(Iop_Add32,
+                                     getIReg(rt),
+                                     mkexpr(t0)))));
+
+         /* Extract bits 32 and 31. */
+         assign(t2, binop(Iop_And32,
+                          unop(Iop_64HIto32, mkexpr(t1)),
+                          mkU32(0x1)));
+         assign(t3, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                unop(Iop_64to32, mkexpr(t1)),
+                                mkU32(0x80000000)),
+                          mkU8(31)));
+         assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+         putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
+         break;
+      }
+
+      case 0x12: {  /* MODSUB */
+         DIP("modsub r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+
+         /* decr_7..0 */
+         assign(t0,
+                unop(Iop_8Uto32,
+                     unop(Iop_16to8,
+                          unop(Iop_32to16, getIReg(rt)))));
+
+         /* lastindex_15..0 */
+         assign(t1,
+                unop(Iop_16Uto32,
+                     binop(Iop_8HLto16,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))),
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         /* temp_15..0 */
+         assign(t2,
+                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                 getIReg(rs),
+                                 mkU32(0x00000000)),
+                           mkexpr(t1),
+                           binop(Iop_Sub32,
+                                 getIReg(rs), mkexpr(t0))));
+         putIReg(rd, mkexpr(t2));
+         break;
+      }
+
+      case 0x14: {  /* RADDU.W.QB */
+         DIP("raddu.w.qb r%u, r%u", rd, rs);
+         vassert(!mode64);
+         putIReg(rd, binop(Iop_Add32,
+                           binop(Iop_Add32,
+                                 unop(Iop_8Uto32,
+                                      unop(Iop_16to8,
+                                           unop(Iop_32to16,
+                                                getIReg(rs)))),
+                                 unop(Iop_8Uto32,
+                                      unop(Iop_16HIto8,
+                                           unop(Iop_32to16,
+                                                getIReg(rs))))),
+                           binop(Iop_Add32,
+                                 unop(Iop_8Uto32,
+                                      unop(Iop_16to8,
+                                           unop(Iop_32HIto16,
+                                                getIReg(rs)))),
+                                 unop(Iop_8Uto32,
+                                      unop(Iop_16HIto8,
+                                           unop(Iop_32HIto16,
+                                                getIReg(rs)))))));
+         break;
+      }
+
+      case 0x16: {  /* ADDQ_S.W */
+         DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Add64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+
+         assign(t3, binop(Iop_And32,
+                          unop(Iop_64HIto32, mkexpr(t0)),
+                          mkU32(0x1)));
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t0)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          mkexpr(t3)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 mkexpr(t3),
+                                                 mkU32(0x0)),
+                                           mkU32(0x7fffffff),
+                                           mkU32(0x80000000)),
+                                unop(Iop_64to32, mkexpr(t0))));
+         break;
+      }
+
+      case 0x17: {  /* SUBQ_S.W */
+         DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Sub64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+
+         assign(t3, binop(Iop_And32,
+                          unop(Iop_64HIto32, mkexpr(t0)),
+                          mkU32(0x1)));
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t0)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          mkexpr(t3)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00100000)),
+                                  getDSPControl()));
+
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                                 mkexpr(t3),
+                                                 mkU32(0x0)),
+                                           mkU32(0x7fffffff),
+                                           mkU32(0x80000000)),
+                                unop(Iop_64to32, mkexpr(t0))));
+         break;
+      }
+
+      case 0x1C: {  /* MULEQ_S.W.PHL */
+         DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I32);
+
+         assign(t0,
+                binop(Iop_Shl32,
+                      binop(Iop_Mul32,
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32HIto16, getIReg(rt))),
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32HIto16, getIReg(rs)))),
+                      mkU8(0x1)));
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0xffff0000)),
+                          mkU32(0x80000000)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0xffff0000)),
+                          mkU32(0x80000000)));
+         assign(t3, IRExpr_ITE(mkexpr(t1),
+                               IRExpr_ITE(mkexpr(t2),
+                                          binop(Iop_Or32,
+                                                getDSPControl(),
+                                                mkU32(0x00200000)),
+                                          getDSPControl()),
+                               getDSPControl()));
+         putDSPControl(mkexpr(t3));
+
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(mkexpr(t2),
+                                           mkU32(0x7fffffff),
+                                           mkexpr(t0)),
+                                mkexpr(t0)));
+         break;
+      }
+
+      case 0x1D: {  /* MULEQ_S.W.PHR */
+         DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t0,
+                binop(Iop_Shl32,
+                      binop(Iop_Mul32,
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32to16, getIReg(rt))),
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32to16, getIReg(rs)))),
+                      mkU8(0x1)));
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0xffff)),
+                          mkU32(0x8000)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0xffff)),
+                          mkU32(0x8000)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  IRExpr_ITE(mkexpr(t2),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(mkexpr(t2),
+                                           mkU32(0x7fffffff),
+                                           mkexpr(t0)),
+                                mkexpr(t0)));
+         break;
+      }
+
+      case 0x1E: {  /* MULQ_S.PH */
+         DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I16);
+         t3 = newTemp(Ity_I16);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t5,
+                unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
+         assign(t6,
+                unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
+
+         assign(t7,
+                unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
+         assign(t8,
+                unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
+
+         assign(t0, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t5),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t6),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000)))));
+         assign(t1, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t7),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t8),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000)))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        binop(Iop_Or32,
+                                              mkexpr(t0),
+                                              mkexpr(t1)),
+                                        mkU32(0x0)),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x200000))));
+
+         assign(t2, unop(Iop_32HIto16,
+                         binop(Iop_Shl32,
+                               unop(Iop_64to32,
+                                    binop(Iop_MullS32,
+                                          mkexpr(t7),
+                                          mkexpr(t8))),
+                               mkU8(0x1))));
+         assign(t3, unop(Iop_32HIto16,
+                         binop(Iop_Shl32,
+                               unop(Iop_64to32,
+                                    binop(Iop_MullS32,
+                                          mkexpr(t5),
+                                          mkexpr(t6))),
+                               mkU8(0x1))));
+         putIReg(rd, binop(Iop_16HLto32,
+                           IRExpr_ITE(binop(Iop_CmpEQ32,
+                                            mkexpr(t1),
+                                            mkU32(0x0)),
+                                      mkexpr(t2),
+                                      mkU16(0x7fff)),
+                           IRExpr_ITE(binop(Iop_CmpEQ32,
+                                            mkexpr(t0),
+                                            mkU32(0x0)),
+                                      mkexpr(t3),
+                                      mkU16(0x7fff))));
+         break;
+      }
+
+      case 0x1F: {  /* MULQ_RS.PH */
+         DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I16);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I16);
+
+         /* Multiply and round lower halfwords. */
+         assign(t0, binop(Iop_Add32,
+                          binop(Iop_Shl32,
+                                binop(Iop_Mul32,
+                                      unop(Iop_16Sto32,
+                                           unop(Iop_32to16,
+                                                getIReg(rt))),
+                                      unop(Iop_16Sto32,
+                                           unop(Iop_32to16,
+                                                getIReg(rs)))),
+                                mkU8(0x1)),
+                          mkU32(0x00008000)));
+         assign(t1, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rt), mkU32(0xffff)),
+                          mkU32(0x8000)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rs), mkU32(0xffff)),
+                          mkU32(0x8000)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  IRExpr_ITE(mkexpr(t2),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         assign(t3, IRExpr_ITE(mkexpr(t1),
+                               IRExpr_ITE(mkexpr(t2),
+                                          mkU16(0x7fff),
+                                          unop(Iop_32HIto16,
+                                               mkexpr(t0))),
+                               unop(Iop_32HIto16, mkexpr(t0))));
+
+         /* Multiply and round higher halfwords. */
+         assign(t4, binop(Iop_Add32,
+                          binop(Iop_Shl32,
+                                binop(Iop_Mul32,
+                                      unop(Iop_16Sto32,
+                                           unop(Iop_32HIto16,
+                                                getIReg(rt))),
+                                      unop(Iop_16Sto32,
+                                           unop(Iop_32HIto16,
+                                                getIReg(rs)))),
+                                mkU8(0x1)),
+                          mkU32(0x00008000)));
+         assign(t5, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0xffff0000)),
+                          mkU32(0x80000000)));
+         assign(t6, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0xffff0000)),
+                          mkU32(0x80000000)));
+         putDSPControl(IRExpr_ITE(mkexpr(t5),
+                                  IRExpr_ITE(mkexpr(t6),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         assign(t7, IRExpr_ITE(mkexpr(t5),
+                               IRExpr_ITE(mkexpr(t6),
+                                          mkU16(0x7fff),
+                                          unop(Iop_32HIto16,
+                                               mkexpr(t4))),
+                               unop(Iop_32HIto16, mkexpr(t4))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_CMPU_EQ_QB( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
+              t15;
+   UInt   rs, rt, rd, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x0: {  /* CMPU.EQ.QB */
+         DIP("cmpu.eq.qb r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+
+         assign(t1,
+                binop(Iop_CmpEQ32,
+                      binop(Iop_And32, getIReg(rs), mkU32(0xff)),
+                      binop(Iop_And32, getIReg(rt), mkU32(0xff))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+         break;
+      }
+
+      case 0x1: {  /* CMPU.LT.QB */
+         DIP("cmpu.lt.qb r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+
+         assign(t1, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+         break;
+      }
+
+      case 0x2: {  /* CMPU.LE.QB */
+         DIP("cmpu.le.qb r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+
+         assign(t1, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+         break;
+      }
+
+      case 0x3: {  /* PICK.QB */
+         DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I8);
+
+         assign(t0, getDSPControl());
+         assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x01000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rs))),
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt)))));
+         assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x02000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs))),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt)))));
+         assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x04000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs))),
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt)))));
+         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x08000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs))),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt)))));
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
+                       binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
+         break;
+      }
+
+      case 0x4: {  /* CMPGU.EQ.QB */
+         DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001), mkU32(0)));
+
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+
+         assign(t4, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      case 0x5: {  /* CMPGU.LT.QB */
+         DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001), mkU32(0)));
+
+         assign(t2, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+
+         assign(t3, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+
+         assign(t4, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      case 0x6: {  /* CMPGU.LE.QB */
+         DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001), mkU32(0)));
+
+         assign(t2, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+
+         assign(t3, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+
+         assign(t4, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      case 0x8: {  /* CMP.EQ.PH */
+         DIP("cmp.eq.ph r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t1, binop(Iop_CmpEQ16,
+                          unop(Iop_32to16, getIReg(rs)),
+                          unop(Iop_32to16, getIReg(rt))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+         assign(t2, binop(Iop_CmpEQ16,
+                          unop(Iop_32HIto16, getIReg(rs)),
+                          unop(Iop_32HIto16, getIReg(rt))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+         break;
+      }
+
+      case 0x9: {  /* CMP.LT.PH */
+         DIP("cmp.lt.ph r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t1, binop(Iop_CmpLT32S,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLT32S,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+         break;
+      }
+
+      case 0xA: {  /* CMP.LE.PH */
+         DIP("cmp.le.ph r%u, r%u", rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t1, binop(Iop_CmpLE32S,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLE32S,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+         break;
+      }
+
+      case 0xB: {  /* PICK.PH */
+         DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I16);
+         t2 = newTemp(Ity_I16);
+
+         assign(t0, getDSPControl());
+
+         assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x01000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_32to16, getIReg(rs)),
+                               unop(Iop_32to16, getIReg(rt))));
+
+         assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0x02000000)),
+                                     mkU32(0x0)),
+                               unop(Iop_32HIto16, getIReg(rs)),
+                               unop(Iop_32HIto16, getIReg(rt))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
+         break;
+      }
+
+      case 0xC: {  /* PRECRQ.QB.PH */
+         DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt);
+         vassert(!mode64);
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16,
+                             unop(Iop_16HIto8,
+                                  unop(Iop_32HIto16, getIReg(rs))),
+                             unop(Iop_16HIto8,
+                                  unop(Iop_32to16, getIReg(rs)))),
+                       binop(Iop_8HLto16,
+                             unop(Iop_16HIto8,
+                                  unop(Iop_32HIto16, getIReg(rt))),
+                             unop(Iop_16HIto8,
+                                  unop(Iop_32to16, getIReg(rt))))));
+         break;
+      }
+
+      case 0xD: {  /* PRECR.QB.PH */
+         DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16,
+                             unop(Iop_16to8,
+                                  unop(Iop_32HIto16, getIReg(rs))),
+                             unop(Iop_16to8,
+                                  unop(Iop_32to16, getIReg(rs)))),
+                       binop(Iop_8HLto16,
+                             unop(Iop_16to8,
+                                  unop(Iop_32HIto16, getIReg(rt))),
+                             unop(Iop_16to8,
+                                  unop(Iop_32to16, getIReg(rt))))));
+         break;
+      }
+
+      case 0xF: {  /* PRECRQU_S.QB.PH */
+         DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I8);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I8);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I8);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I8);
+         t11 = newTemp(Ity_I1);
+         t12 = newTemp(Ity_I32);
+         t13 = newTemp(Ity_I8);
+         t14 = newTemp(Ity_I1);
+         t15 = newTemp(Ity_I32);
+
+         assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                     mkU32(0x7f80),
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32to16,
+                                                      getIReg(rs))),
+                                           mkU32(0x7fff))),
+                               mkU8(0xff),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         binop(Iop_Shl32,
+                                               getIReg(rs),
+                                               mkU8(1))))));
+         assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32to16,
+                                                      getIReg(rs))),
+                                           mkU32(0x00008000)),
+                                     mkU32(0x0)),
+                               mkexpr(t4),
+                               mkU8(0x0)));
+         assign(t5, binop(Iop_And32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16,
+                                    getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t6, binop(Iop_CmpLT32U,
+                          mkU32(0x7f80),
+                          binop(Iop_And32,
+                                unop(Iop_16Uto32,
+                                     unop(Iop_32to16,
+                                          getIReg(rs))),
+                                mkU32(0x7fff))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        mkexpr(t5),
+                                        mkU32(0x0)),
+                                  IRExpr_ITE(mkexpr(t6),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00400000)
+                                                  ),
+                                             getDSPControl()),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00400000))));
+
+         assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                     mkU32(0x7f80),
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32HIto16,
+                                                      getIReg(rs))),
+                                           mkU32(0x7fff))),
+                               mkU8(0xff),
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         binop(Iop_Shl32,
+                                               getIReg(rs),
+                                               mkU8(1))))));
+         assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32HIto16,
+                                                      getIReg(rs))),
+                                           mkU32(0x00008000)),
+                                     mkU32(0x0)),
+                               mkexpr(t7),
+                               mkU8(0x0)));
+         assign(t8, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                unop(Iop_16Uto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs))),
+                                mkU32(0x00008000)),
+                          mkU32(0x0)));
+         assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                     mkU32(0x7f80),
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32HIto16,
+                                                      getIReg(rs))),
+                                           mkU32(0x7fff))),
+                               binop(Iop_Or32,
+                                     getDSPControl(),
+                                     mkU32(0x00400000)),
+                               getDSPControl()));
+         putDSPControl(IRExpr_ITE(mkexpr(t8),
+                                  mkexpr(t9),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00400000))));
+
+         assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                      mkU32(0x7f80),
+                                      binop(Iop_And32,
+                                            unop(Iop_16Uto32,
+                                                 unop(Iop_32to16,
+                                                       getIReg(rt))),
+                                            mkU32(0x7fff))),
+                                mkU8(0xff),
+                                unop(Iop_16HIto8,
+                                     unop(Iop_32to16,
+                                          binop(Iop_Shl32,
+                                                getIReg(rt),
+                                                mkU8(1))))));
+         assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32to16,
+                                                      getIReg(rt))),
+                                           mkU32(0x00008000)),
+                                     mkU32(0x0)),
+                               mkexpr(t10),
+                               mkU8(0x0)));
+         assign(t11, binop(Iop_CmpEQ32,
+                           binop(Iop_And32,
+                                 unop(Iop_16Uto32,
+                                      unop(Iop_32to16,
+                                           getIReg(rt))),
+                                 mkU32(0x00008000)),
+                           mkU32(0x0)));
+         assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                      mkU32(0x7f80),
+                                      binop(Iop_And32,
+                                            unop(Iop_16Uto32,
+                                                 unop(Iop_32to16,
+                                                       getIReg(rt))),
+                                            mkU32(0x7fff))),
+                                binop(Iop_Or32,
+                                      getDSPControl(),
+                                      mkU32(0x00400000)),
+                                getDSPControl()));
+         putDSPControl(IRExpr_ITE(mkexpr(t11),
+                                  mkexpr(t12),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00400000))));
+
+         assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                      mkU32(0x7f80),
+                                      binop(Iop_And32,
+                                            unop(Iop_16Uto32,
+                                                 unop(Iop_32HIto16,
+                                                       getIReg(rt))),
+                                            mkU32(0x7fff))),
+                                mkU8(0xff),
+                                unop(Iop_16HIto8,
+                                     unop(Iop_32HIto16,
+                                          binop(Iop_Shl32,
+                                                getIReg(rt),
+                                                mkU8(1))))));
+         assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           unop(Iop_16Uto32,
+                                                unop(Iop_32HIto16,
+                                                      getIReg(rt))),
+                                           mkU32(0x00008000)),
+                                     mkU32(0x0)),
+                               mkexpr(t13),
+                               mkU8(0x0)));
+         assign(t14, binop(Iop_CmpEQ32,
+                           binop(Iop_And32,
+                                 unop(Iop_16Uto32,
+                                      unop(Iop_32HIto16,
+                                           getIReg(rt))),
+                                 mkU32(0x00008000)),
+                           mkU32(0x0)));
+         assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
+                                      mkU32(0x7f80),
+                                      binop(Iop_And32,
+                                            unop(Iop_16Uto32,
+                                                 unop(Iop_32HIto16,
+                                                       getIReg(rt))),
+                                            mkU32(0x7fff))),
+                                binop(Iop_Or32,
+                                      getDSPControl(),
+                                      mkU32(0x00400000)),
+                                getDSPControl()));
+         putDSPControl(IRExpr_ITE(mkexpr(t14),
+                                  mkexpr(t15),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00400000))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           binop(Iop_8HLto16,
+                                 mkexpr(t1), mkexpr(t0)),
+                           binop(Iop_8HLto16,
+                                 mkexpr(t3), mkexpr(t2))));
+         break;
+      }
+
+      case 0x14: {  /* PRECRQ.PH.W */
+         DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt);
+         vassert(!mode64);
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32HIto16, getIReg(rs)),
+                           unop(Iop_32HIto16, getIReg(rt))));
+         break;
+      }
+
+      case 0x15: {  /* PRECRQ_RS.PH.W */
+         DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_Add64,
+                          binop(Iop_32HLto64,
+                                binop(Iop_Shr32,
+                                      binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x80000000)),
+                                      mkU8(31)),
+                                getIReg(rs)),
+                          mkU64(0x0000000000008000ULL)));
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t0)),
+                                mkU32(0x1)),
+                          binop(Iop_And32,
+                                binop(Iop_Shr32,
+                                      unop(Iop_64to32, mkexpr(t0)),
+                                      mkU8(31)),
+                                mkU32(0x1))));
+         assign(t2, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x7fffffff),
+                               unop(Iop_64to32, mkexpr(t0))));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  getDSPControl()));
+         assign(t3, binop(Iop_Add64,
+                          binop(Iop_32HLto64,
+                                binop(Iop_Shr32,
+                                      binop(Iop_And32,
+                                            getIReg(rt),
+                                            mkU32(0x80000000)),
+                                      mkU8(31)),
+                                getIReg(rt)),
+                          mkU64(0x0000000000008000ULL)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t3)),
+                                mkU32(0x1)),
+                          binop(Iop_And32,
+                                binop(Iop_Shr32,
+                                      unop(Iop_64to32, mkexpr(t3)),
+                                      mkU8(31)),
+                                mkU32(0x1))));
+         assign(t5, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x7fffffff),
+                               unop(Iop_64to32, mkexpr(t3))));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  getDSPControl()));
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32HIto16, mkexpr(t2)),
+                           unop(Iop_32HIto16, mkexpr(t5))));
+         break;
+      }
+
+      case 0x1E: {  /* PRECR_SRA.PH.W */
+         DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd);
+         vassert(!mode64);
+
+         if (0 == rd) {
+            putIReg(rt, binop(Iop_16HLto32,
+                              unop(Iop_32to16, getIReg(rt)),
+                              unop(Iop_32to16, getIReg(rs))));
+         } else {
+            putIReg(rt, binop(Iop_16HLto32,
+                              unop(Iop_32to16, binop(Iop_Sar32,
+                                    getIReg(rt),
+                                    mkU8(rd))),
+                              unop(Iop_32to16, binop(Iop_Sar32,
+                                    getIReg(rs),
+                                    mkU8(rd)))));
+         }
+
+         break;
+      }
+
+      case 0x1F: {  /* PRECR_SRA_R.PH.W */
+         DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+
+         if (0 == rd) {
+            putIReg(rt, binop(Iop_16HLto32,
+                              unop(Iop_32to16, getIReg(rt)),
+                              unop(Iop_32to16, getIReg(rs))));
+         } else {
+            assign(t0, binop(Iop_Shr32,
+                             binop(Iop_Add32,
+                                   binop(Iop_Sar32,
+                                         getIReg(rt),
+                                         mkU8(rd - 1)),
+                                   mkU32(0x1)),
+                             mkU8(0x1)));
+            assign(t1, binop(Iop_Shr32,
+                             binop(Iop_Add32,
+                                   binop(Iop_Sar32,
+                                         getIReg(rs),
+                                         mkU8(rd - 1)),
+                                   mkU32(0x1)),
+                             mkU8(0x1)));
+            putIReg(rt, binop(Iop_16HLto32,
+                              unop(Iop_32to16, mkexpr(t0)),
+                              unop(Iop_32to16, mkexpr(t1))));
+         };
+
+         break;
+      }
+
+      case 0xE: {  /* PACKRL.PH */
+         DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, getIReg(rs)),
+                           unop(Iop_32HIto16, getIReg(rt))));
+         break;
+      }
+
+      case 0x18: {  /* CMPGDU.EQ.QB */
+         DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1,
+                binop(Iop_CmpEQ32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpEQ32,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      case 0x19: {  /* CMPGDU.LT.QB */
+         DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpLT32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      case 0x1A: {  /* CMPGDU.LE.QB */
+         DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               mkU32(0x00000001),
+                               mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x01000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfeffffff))));
+
+         assign(t2, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16, getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32to16,
+                                         getIReg(rt))))));
+         assign(t6, IRExpr_ITE(mkexpr(t2),
+                               mkU32(0x00000002), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x02000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfdffffff))));
+
+         assign(t3, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16to8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t7, IRExpr_ITE(mkexpr(t3),
+                               mkU32(0x00000004), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x04000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xfbffffff))));
+
+         assign(t4, binop(Iop_CmpLE32U,
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rs)))),
+                          unop(Iop_8Uto32,
+                               unop(Iop_16HIto8,
+                                    unop(Iop_32HIto16,
+                                         getIReg(rt))))));
+         assign(t8, IRExpr_ITE(mkexpr(t4),
+                               mkU32(0x00000008), mkU32(0)));
+         putDSPControl(IRExpr_ITE(mkexpr(t4),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x08000000)),
+                                  binop(Iop_And32,
+                                        getDSPControl(),
+                                        mkU32(0xf7ffffff))));
+
+         putIReg(rd, binop(Iop_Or32,
+                           binop(Iop_Or32,
+                                 binop(Iop_Or32,
+                                       mkexpr(t5), mkexpr(t6)),
+                                 mkexpr(t7)),
+                           mkexpr(t8)));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_SHLL_QB( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
+              t15, t16, t17;
+   UInt   rs, rt, rd, sa;
+
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x0: {  /* SHLL.QB */
+         DIP("shll.qb r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I1);
+         t10 = newTemp(Ity_I1);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            /* Shift bits 7..0 and 23..16. */
+            assign(t0, binop(Iop_Shl32,
+                             binop(Iop_And32,
+                                   getIReg(rt),
+                                   mkU32(0x00ff00ff)),
+                             mkU8(rs)));
+            assign(t1, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t0),
+                                   mkU32(0xff000000)),
+                             mkU32(0x00000000)));
+            assign(t2, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t0),
+                                   mkU32(0xff000000)),
+                             mkU32(0xff000000)));
+            assign(t7, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t0),
+                                   mkU32(0x0000ff00)),
+                             mkU32(0x00000000)));
+            assign(t8, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t0),
+                                   mkU32(0x0000ff00)),
+                             mkU32(0x000ff00)));
+            /* Shift bits 15..8 and 31..24. */
+            assign(t3, binop(Iop_Shl32,
+                             binop(Iop_Shr32,
+                                   binop(Iop_And32,
+                                         getIReg(rt),
+                                         mkU32(0xff00ff00)),
+                                   mkU8(8)),
+                             mkU8(rs)));
+            assign(t4, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t3),
+                                   mkU32(0xff000000)),
+                             mkU32(0x00000000)));
+            assign(t5, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t3),
+                                   mkU32(0xff000000)),
+                             mkU32(0xff000000)));
+            assign(t9, binop(Iop_CmpNE32,
+                             binop(Iop_And32,
+                                   mkexpr(t3),
+                                   mkU32(0x0000ff00)),
+                             mkU32(0x00000000)));
+            assign(t10, binop(Iop_CmpNE32,
+                              binop(Iop_And32,
+                                    mkexpr(t3),
+                                    mkU32(0x0000ff00)),
+                              mkU32(0x0000ff00)));
+
+            assign(t6, binop(Iop_Or32,
+                             binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t1)),
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t2))),
+                                   binop(Iop_And32,
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t7)),
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t8)))),
+                             binop(Iop_Or32,
+                                   binop(Iop_And32,
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t4)),
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t5))),
+                                   binop(Iop_And32,
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t9)),
+                                         unop(Iop_1Uto32,
+                                              mkexpr(t10))))));
+
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                           mkexpr(t6),
+                                           mkU32(0x0)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putIReg(rd, binop(Iop_Or32,
+                              binop(Iop_Shl32,
+                                    binop(Iop_And32,
+                                          mkexpr(t3),
+                                          mkU32(0x00ff00ff)),
+                                    mkU8(8)),
+                              binop(Iop_And32,
+                                    mkexpr(t0),
+                                    mkU32(0x00ff00ff))));
+         }
+
+         break;
+      }
+
+      case 0x3: {  /* SHRL.QB */
+         DIP("shrl.qb r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I8);
+         t9 = newTemp(Ity_I32);
+
+         assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
+         assign(t0, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t1, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               mkexpr(t0),
+                               unop(Iop_32to8, mkexpr(t9)))));
+
+         assign(t2, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t3, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               mkexpr(t2),
+                               unop(Iop_32to8, mkexpr(t9)))));
+
+         assign(t4, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t5, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               mkexpr(t4),
+                               unop(Iop_32to8, mkexpr(t9)))));
+
+         assign(t6, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t7, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               mkexpr(t6),
+                               unop(Iop_32to8, mkexpr(t9)))));
+         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      mkexpr(t9),
+                                      mkU32(0x0)),
+                                getIReg(rt),
+                                binop(Iop_16HLto32,
+                                      binop(Iop_8HLto16,
+                                            mkexpr(t7),
+                                            mkexpr(t5)),
+                                      binop(Iop_8HLto16,
+                                            mkexpr(t3),
+                                            mkexpr(t1)))));
+         break;
+      }
+
+      case 0x2: {  /* SHLLV.QB */
+         DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I1);
+         t10 = newTemp(Ity_I1);
+         t11 = newTemp(Ity_I8);
+
+         assign(t11, unop(Iop_32to8,
+                          binop(Iop_And32,
+                                getIReg(rs),
+                                mkU32(0x7))));
+         /* Shift bits 7..0 and 23..16. */
+         assign(t0, binop(Iop_Shl32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x00ff00ff)),
+                          mkexpr(t11)));
+         assign(t1, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0xff000000)),
+                          mkU32(0x00000000)));
+         assign(t2, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0xff000000)),
+                          mkU32(0xff000000)));
+         assign(t7, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x0000ff00)),
+                          mkU32(0x00000000)));
+         assign(t8, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t0),
+                                mkU32(0x0000ff00)),
+                          mkU32(0x000ff00)));
+         /* Shift bits 15..8 and 31..24. */
+         assign(t3, binop(Iop_Shl32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0xff00ff00)),
+                                mkU8(8)),
+                          mkexpr(t11)));
+         assign(t4, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t3),
+                                mkU32(0xff000000)),
+                          mkU32(0x00000000)));
+         assign(t5, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t3),
+                                mkU32(0xff000000)),
+                          mkU32(0xff000000)));
+         assign(t9, binop(Iop_CmpNE32,
+                          binop(Iop_And32,
+                                mkexpr(t3),
+                                mkU32(0x0000ff00)),
+                          mkU32(0x00000000)));
+         assign(t10, binop(Iop_CmpNE32,
+                           binop(Iop_And32,
+                                 mkexpr(t3),
+                                 mkU32(0x0000ff00)),
+                           mkU32(0x0000ff00)));
+
+         assign(t6, binop(Iop_Or32,
+                          binop(Iop_Or32,
+                                binop(Iop_And32,
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t1)),
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t2))),
+                                binop(Iop_And32,
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t7)),
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t8)))),
+                          binop(Iop_Or32,
+                                binop(Iop_And32,
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t4)),
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t5))),
+                                binop(Iop_And32,
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t9)),
+                                      unop(Iop_1Uto32,
+                                           mkexpr(t10))))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t6),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  getDSPControl()));
+         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      unop(Iop_8Uto32, mkexpr(t11)),
+                                      mkU32(0)),
+                                getIReg(rt),
+                                binop(Iop_Or32,
+                                      binop(Iop_Shl32,
+                                            binop(Iop_And32,
+                                                  mkexpr(t3),
+                                                  mkU32(0xff00ff)),
+                                            mkU8(8)),
+                                      binop(Iop_And32,
+                                            mkexpr(t0),
+                                            mkU32(0x00ff00ff)))));
+         break;
+      }
+
+      case 0x1: {  /* SHRLV.QB */
+         DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I8);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I8);
+
+         assign(t0, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_32to8, getIReg(rt))),
+                               mkU8(rs))));
+         assign(t1, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_16HIto8,
+                                         unop(Iop_32to16,
+                                              getIReg(rt)))),
+                               mkU8(rs))));
+         assign(t2, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_16to8,
+                                         unop(Iop_32HIto16,
+                                              getIReg(rt)))),
+                               mkU8(rs))));
+         assign(t3, unop(Iop_32to8,
+                         binop(Iop_Shr32,
+                               unop(Iop_8Uto32,
+                                    unop(Iop_16HIto8,
+                                         unop(Iop_32HIto16,
+                                              getIReg(rt)))),
+                               mkU8(rs))));
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
+                       binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
+         break;
+      }
+
+      case 0x4: {  /* SHRA.QB */
+         DIP("shra.qb r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I32);
+
+         /* ========== GPR[rt]_31..24 ========== */
+         assign(t1,
+                unop(Iop_8Uto32,
+                     unop(Iop_16HIto8,
+                          unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t2,
+                binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
+         /* tempD_7..0 */
+         assign(t0,
+                binop(Iop_Or32,
+                      mkexpr(t2),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t1),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
+
+         /* ========== GPR[rt]_23..16 ========== */
+         assign(t4,
+                unop(Iop_8Uto32,
+                     unop(Iop_16to8,
+                          unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
+         /* tempC_7..0 */
+         assign(t3,
+                binop(Iop_Or32,
+                      mkexpr(t5),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t4),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
+
+         /* ========== GPR[rt]_15..8 ========== */
+         assign(t7,
+                unop(Iop_8Uto32,
+                     unop(Iop_16HIto8,
+                          unop(Iop_32to16, getIReg(rt)))));
+         assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
+         /* tempB_7..0 */
+         assign(t6,
+                binop(Iop_Or32,
+                      mkexpr(t8),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t7),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
+
+         /* ========== GPR[rt]_7..0 ========== */
+         assign(t10,
+                unop(Iop_8Uto32,
+                     unop(Iop_16to8,
+                          unop(Iop_32to16, getIReg(rt)))));
+         assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
+         /* tempB_7..0 */
+         assign(t9,
+                binop(Iop_Or32,
+                      mkexpr(t11),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t10),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
+
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16,
+                             unop(Iop_32to8, mkexpr(t0)),
+                             unop(Iop_32to8, mkexpr(t3))),
+                       binop(Iop_8HLto16,
+                             unop(Iop_32to8, mkexpr(t6)),
+                             unop(Iop_32to8, mkexpr(t9)))));
+         break;
+      }
+
+      case 0x5: {  /* SHRA_R.QB */
+         DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I8);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            assign(t0, unop(Iop_8Sto32,
+                            unop(Iop_16to8,
+                                 unop(Iop_32to16, getIReg(rt)))));
+            assign(t1, unop(Iop_32to8,
+                            binop(Iop_Sar32,
+                                  binop(Iop_Add32,
+                                        mkexpr(t0),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(rs - 1))),
+                                  mkU8(rs))));
+
+            assign(t2, unop(Iop_8Sto32,
+                            unop(Iop_16HIto8,
+                                 unop(Iop_32to16, getIReg(rt)))));
+            assign(t3, unop(Iop_32to8,
+                            binop(Iop_Sar32,
+                                  binop(Iop_Add32,
+                                        mkexpr(t2),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(rs - 1))),
+                                  mkU8(rs))));
+
+            assign(t4, unop(Iop_8Sto32,
+                            unop(Iop_16to8,
+                                 unop(Iop_32HIto16, getIReg(rt)))));
+            assign(t5, unop(Iop_32to8,
+                            binop(Iop_Sar32,
+                                  binop(Iop_Add32,
+                                        mkexpr(t4),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(rs - 1))),
+                                  mkU8(rs))));
+
+            assign(t6, unop(Iop_8Sto32,
+                            unop(Iop_16HIto8,
+                                 unop(Iop_32HIto16, getIReg(rt)))));
+            assign(t7, unop(Iop_32to8,
+                            binop(Iop_Sar32,
+                                  binop(Iop_Add32,
+                                        mkexpr(t6),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(rs - 1))),
+                                  mkU8(rs))));
+            putIReg(rd, binop(Iop_16HLto32,
+                              binop(Iop_8HLto16,
+                                    mkexpr(t7), mkexpr(t5)),
+                              binop(Iop_8HLto16,
+                                    mkexpr(t3), mkexpr(t1))));
+         }
+
+         break;
+      }
+
+      case 0x6: {  /* SHRAV.QB */
+         DIP("shrav.qb r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I32);
+
+         /* ========== GPR[rt]_31..24 ========== */
+         assign(t1,
+                unop(Iop_8Uto32,
+                     unop(Iop_16HIto8,
+                          unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t2,
+                binop(Iop_Shr32,
+                      mkexpr(t1),
+                      unop(Iop_32to8, binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x7)))));
+         /* tempD_7..0 */
+         assign(t0,
+                binop(Iop_Or32,
+                      mkexpr(t2),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t1),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8,
+                                  mkU8(0x8),
+                                  unop(Iop_32to8, binop(Iop_And32,
+                                        getIReg(rs),
+                                        mkU32(0x7)))
+                                 ))));
+
+         /* ========== GPR[rt]_23..16 ========== */
+         assign(t4,
+                unop(Iop_8Uto32,
+                     unop(Iop_16to8,
+                          unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t5,
+                binop(Iop_Shr32,
+                      mkexpr(t4),
+                      unop(Iop_32to8, binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x7)))));
+         /* tempC_7..0 */
+         assign(t3,
+                binop(Iop_Or32,
+                      mkexpr(t5),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t4),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8,
+                                  mkU8(0x8),
+                                  unop(Iop_32to8, binop(Iop_And32,
+                                        getIReg(rs),
+                                        mkU32(0x7)))
+                                 ))));
+
+         /* ========== GPR[rt]_15..8 ========== */
+         assign(t7,
+                unop(Iop_8Uto32,
+                     unop(Iop_16HIto8,
+                          unop(Iop_32to16, getIReg(rt)))));
+         assign(t8,
+                binop(Iop_Shr32,
+                      mkexpr(t7),
+                      unop(Iop_32to8, binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x7)))));
+         /* tempB_7..0 */
+         assign(t6,
+                binop(Iop_Or32,
+                      mkexpr(t8),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t7),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8,
+                                  mkU8(0x8),
+                                  unop(Iop_32to8, binop(Iop_And32,
+                                        getIReg(rs),
+                                        mkU32(0x7)))
+                                 ))));
+
+         /* ========== GPR[rt]_7..0 ========== */
+         assign(t10,
+                unop(Iop_8Uto32,
+                     unop(Iop_16to8,
+                          unop(Iop_32to16, getIReg(rt)))));
+         assign(t11,
+                binop(Iop_Shr32,
+                      mkexpr(t10),
+                      unop(Iop_32to8, binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x7)))));
+         /* tempB_7..0 */
+         assign(t9,
+                binop(Iop_Or32,
+                      mkexpr(t11),
+                      binop(Iop_Shl32,
+                            IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkexpr(t10),
+                                                   mkU32(0x00000080)
+                                                  ),
+                                             mkU32(0x00000080)),
+                                       mkU32(0xFFFFFFFF),
+                                       mkU32(0x00000000)),
+                            binop(Iop_Sub8,
+                                  mkU8(0x8),
+                                  unop(Iop_32to8, binop(Iop_And32,
+                                        getIReg(rs),
+                                        mkU32(0x7)))
+                                 ))));
+
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       binop(Iop_8HLto16,
+                             unop(Iop_32to8,
+                                  IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkU32(rs),
+                                                   mkU32(0x7)
+                                                  ),
+                                             mkU32(0x0)),
+                                             mkexpr(t1),
+                                             mkexpr(t0))),
+                             unop(Iop_32to8,
+                                  IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkU32(rs),
+                                                   mkU32(0x7)
+                                                  ),
+                                             mkU32(0x0)),
+                                             mkexpr(t2),
+                                             mkexpr(t3)))),
+                       binop(Iop_8HLto16,
+                             unop(Iop_32to8,
+                                  IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkU32(rs),
+                                                   mkU32(0x7)
+                                                  ),
+                                             mkU32(0x0)),
+                                             mkexpr(t5),
+                                             mkexpr(t6))),
+                             unop(Iop_32to8,
+                                  IRExpr_ITE(binop(Iop_CmpEQ32,
+                                             binop(Iop_And32,
+                                                   mkU32(rs),
+                                                   mkU32(0x7)
+                                                  ),
+                                             mkU32(0x0)),
+                                             mkexpr(t8),
+                                             mkexpr(t9))))));
+         break;
+      }
+
+      case 0x7: {  /* SHRAV_R.QB */
+         DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I8);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I8);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I8);
+         t8 = newTemp(Ity_I8);
+         t9 = newTemp(Ity_I32);
+
+         assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
+         assign(t8, unop(Iop_32to8,
+                         binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
+         assign(t0, unop(Iop_8Sto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t1, unop(Iop_32to8,
+                         binop(Iop_Sar32,
+                               binop(Iop_Add32,
+                                     mkexpr(t0),
+                                     binop(Iop_Shl32,
+                                           mkU32(0x1),
+                                           mkexpr(t8))),
+                               unop(Iop_32to8,
+                                    mkexpr(t9)))));
+
+         assign(t2, unop(Iop_8Sto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t3, unop(Iop_32to8,
+                         binop(Iop_Sar32,
+                               binop(Iop_Add32,
+                                     mkexpr(t2),
+                                     binop(Iop_Shl32,
+                                           mkU32(0x1),
+                                           mkexpr(t8))),
+                               unop(Iop_32to8, mkexpr(t9)))));
+
+         assign(t4, unop(Iop_8Sto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t5, unop(Iop_32to8,
+                         binop(Iop_Sar32,
+                               binop(Iop_Add32,
+                                     mkexpr(t4),
+                                     binop(Iop_Shl32,
+                                           mkU32(0x1),
+                                           mkexpr(t8))),
+                               unop(Iop_32to8, mkexpr(t9)))));
+
+         assign(t6, unop(Iop_8Sto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t7, unop(Iop_32to8,
+                         binop(Iop_Sar32,
+                               binop(Iop_Add32,
+                                     mkexpr(t6),
+                                     binop(Iop_Shl32,
+                                           mkU32(0x1),
+                                           mkexpr(t8))),
+                               unop(Iop_32to8, mkexpr(t9)))));
+         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      mkexpr(t9),
+                                      mkU32(0x0)),
+                                getIReg(rt),
+                                binop(Iop_16HLto32,
+                                      binop(Iop_8HLto16,
+                                            mkexpr(t7),
+                                            mkexpr(t5)),
+                                      binop(Iop_8HLto16,
+                                            mkexpr(t3),
+                                            mkexpr(t1)))));
+         break;
+      }
+
+      case 0x8: {  /* SHLL.PH */
+         DIP("shll.ph r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            /* Shift lower 16 bits. */
+            assign(t0, binop(Iop_Shl32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32to16, getIReg(rt))),
+                             mkU8(rs)));
+
+            assign(t1, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t0),
+                                        mkU8(16)),
+                                  mkU32(0))));
+            assign(t2, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t0),
+                                        mkU8(16)),
+                                  mkU32(0xffffffff))));
+            assign(t3, binop(Iop_And32,
+                             mkexpr(t1),
+                             mkexpr(t2)));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t3),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           binop(Iop_And32,
+                                                 getIReg(rt),
+                                                 mkU32(0x00008000)),
+                                           binop(Iop_And32,
+                                                 mkexpr(t0),
+                                                 mkU32(0x00008000))
+                                          ),
+                                     getDSPControl(),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000))));
+            /* Shift higher 16 bits. */
+            assign(t4, binop(Iop_Shl32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32HIto16, getIReg(rt))),
+                             mkU8(rs)));
+
+            assign(t5, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t4),
+                                        mkU8(16)),
+                                  mkU32(0))));
+            assign(t6, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t4),
+                                        mkU8(16)),
+                                  mkU32(0xffffffff))));
+            assign(t7, binop(Iop_And32,
+                             mkexpr(t5),
+                             mkexpr(t6)));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t7),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t7),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           binop(Iop_And32,
+                                                 getIReg(rt),
+                                                 mkU32(0x80000000)),
+                                           binop(Iop_Shl32,
+                                                 binop(Iop_And32,
+                                                       mkexpr(t4),
+                                                       mkU32(0x00008000)),
+                                                 mkU8(16))
+                                          ),
+                                     getDSPControl(),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000))));
+            putIReg(rd, binop(Iop_16HLto32,
+                              unop(Iop_32to16, mkexpr(t4)),
+                              unop(Iop_32to16, mkexpr(t0))));
+         }
+
+         break;
+      }
+
+      case 0x9: {  /* SHRA.PH */
+         DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            assign(t0, binop(Iop_Sar32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32to16, getIReg(rt))),
+                             mkU8(rs)));
+            assign(t1, binop(Iop_Sar32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32HIto16, getIReg(rt))),
+                             mkU8(rs)));
+            putIReg(rd, binop(Iop_16HLto32,
+                              unop(Iop_32to16, mkexpr(t1)),
+                              unop(Iop_32to16, mkexpr(t0))));
+         }
+
+         break;
+      }
+
+      case 0xA: {  /* SHLLV.PH */
+         DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I32);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
+
+         /* Shift lower 16 bits. */
+         assign(t2, binop(Iop_Shl32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x00000000)));
+         assign(t4, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0xffffffff)));
+         assign(t10, binop(Iop_And32,
+                           unop(Iop_1Sto32, mkexpr(t3)),
+                           unop(Iop_1Sto32, mkexpr(t4))));
+         assign(t5, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x00008000)),
+                          mkU8(15)));
+         assign(t12, binop(Iop_CmpEQ32,
+                           mkexpr(t5),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       mkexpr(t2),
+                                       mkU32(0x00008000)),
+                                 mkU8(15))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t10),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  IRExpr_ITE(mkexpr(t12),
+                                             getDSPControl(),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x400000)))
+                                 ));
+         /* Shift higher 16 bits. */
+         assign(t6, binop(Iop_Shl32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         assign(t7, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t6))),
+                          mkU32(0x00000000)));
+         assign(t8, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t6))),
+                          mkU32(0xffffffff)));
+         assign(t11, binop(Iop_And32,
+                           unop(Iop_1Sto32, mkexpr(t7)),
+                           unop(Iop_1Sto32, mkexpr(t8))));
+
+         assign(t9, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x80000000)),
+                          mkU8(31)));
+         assign(t13, binop(Iop_CmpEQ32,
+                           mkexpr(t9),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       mkexpr(t6),
+                                       mkU32(0x00008000)),
+                                 mkU8(15))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t11),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  IRExpr_ITE(mkexpr(t13),
+                                             getDSPControl(),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x400000)))
+                                 ));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t6)),
+                           unop(Iop_32to16, mkexpr(t2))));
+         break;
+      }
+
+      case 0xB: {  /* SHRAV.PH */
+         DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
+         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
+         assign(t2, binop(Iop_Sar32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+         assign(t3, binop(Iop_Sar32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+         putIReg(rd,
+                 binop(Iop_16HLto32,
+                       IRExpr_ITE(mkexpr(t1),
+                                  unop(Iop_32HIto16, getIReg(rt)),
+                                  unop(Iop_32to16, mkexpr(t3))),
+                       IRExpr_ITE(mkexpr(t1),
+                                  unop(Iop_32to16, getIReg(rt)),
+                                  unop(Iop_32to16, mkexpr(t2)))));
+         break;
+      }
+
+      case 0xC: {  /* SHLL_S.PH */
+         DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I32);
+         t12 = newTemp(Ity_I32);
+         t13 = newTemp(Ity_I32);
+         t14 = newTemp(Ity_I32);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            /* Shift lower 16 bits. */
+            assign(t0, binop(Iop_Shl32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32to16, getIReg(rt))),
+                             mkU8(rs)));
+
+            assign(t1, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t0),
+                                        mkU8(16)),
+                                  mkU32(0))));
+            assign(t2, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t0),
+                                        mkU8(16)),
+                                  mkU32(0xffffffff))));
+            assign(t3, binop(Iop_And32,
+                             mkexpr(t1),
+                             mkexpr(t2)));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t3),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           binop(Iop_And32,
+                                                 getIReg(rt),
+                                                 mkU32(0x00008000)),
+                                           binop(Iop_And32,
+                                                 mkexpr(t0),
+                                                 mkU32(0x00008000))
+                                          ),
+                                     getDSPControl(),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000))));
+            assign(t8,
+                   IRExpr_ITE(binop(Iop_CmpEQ32,
+                                    mkexpr(t3),
+                                    mkU32(0x1)),
+                              IRExpr_ITE(binop(Iop_CmpEQ32,
+                                               binop(Iop_And32,
+                                                     getIReg(rt),
+                                                     mkU32(0x8000)),
+                                               mkU32(0)),
+                                         mkU32(0x00007fff),
+                                         mkU32(0x00008000)),
+                              binop(Iop_And32,
+                                    mkexpr(t0),
+                                    mkU32(0x0000ffff))));
+            assign(t10,
+                   IRExpr_ITE(binop(Iop_CmpEQ32,
+                                    binop(Iop_And32,
+                                          getIReg(rt),
+                                          mkU32(0x00008000)),
+                                    binop(Iop_And32,
+                                          mkexpr(t0),
+                                          mkU32(0x00008000))),
+                              mkexpr(t8),
+                              IRExpr_ITE(binop(Iop_CmpEQ32,
+                                               binop(Iop_And32,
+                                                     getIReg(rt),
+                                                     mkU32(0x8000)),
+                                               mkU32(0)),
+                                         mkU32(0x00007fff),
+                                         mkU32(0x00008000))));
+            /* Shift higher 16 bits. */
+            assign(t4, binop(Iop_Shl32,
+                             unop(Iop_16Sto32,
+                                  unop(Iop_32HIto16, getIReg(rt))),
+                             mkU8(rs)));
+
+            assign(t5, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t4),
+                                        mkU8(16)),
+                                  mkU32(0))));
+            assign(t6, unop(Iop_1Uto32,
+                            binop(Iop_CmpNE32,
+                                  binop(Iop_Sar32,
+                                        mkexpr(t4),
+                                        mkU8(16)),
+                                  mkU32(0xffffffff))));
+            assign(t7, binop(Iop_And32,
+                             mkexpr(t5),
+                             mkexpr(t6)));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t7),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           mkexpr(t7),
+                                           mkU32(0x1)),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000)),
+                                     getDSPControl()));
+            assign(t12, binop(Iop_Shl32,
+                              binop(Iop_And32,
+                                    mkexpr(t4),
+                                    mkU32(0x8000)),
+                              mkU8(16)));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           binop(Iop_And32,
+                                                 getIReg(rt),
+                                                 mkU32(0x80000000)),
+                                           mkexpr(t12)),
+                                     getDSPControl(),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000))));
+            assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                         binop(Iop_And32,
+                                               getIReg(rt),
+                                               mkU32(0x80000000)),
+                                         mkU32(0)),
+                                   mkU32(0x7fff0000),
+                                   mkU32(0x80000000)));
+            assign(t9,
+                   IRExpr_ITE(binop(Iop_CmpEQ32,
+                                    mkexpr(t7),
+                                    mkU32(0x1)),
+                              mkexpr(t13),
+                              binop(Iop_Shl32,
+                                    binop(Iop_And32,
+                                          mkexpr(t4),
+                                          mkU32(0x0000ffff)),
+                                    mkU8(16))));
+            assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                         binop(Iop_And32,
+                                               getIReg(rt),
+                                               mkU32(0x80000000)),
+                                         mkU32(0)),
+                                   mkU32(0x7fff0000),
+                                   mkU32(0x80000000)));
+            assign(t11,
+                   IRExpr_ITE(binop(Iop_CmpEQ32,
+                                    binop(Iop_And32,
+                                          getIReg(rt),
+                                          mkU32(0x80000000)),
+                                    binop(Iop_Shl32,
+                                          binop(Iop_And32,
+                                                mkexpr(t4),
+                                                mkU32(0x00008000)),
+                                          mkU8(16))),
+                              mkexpr(t9),
+                              mkexpr(t14)));
+            putIReg(rd, binop(Iop_Or32,
+                              mkexpr(t10),
+                              mkexpr(t11)));
+         }
+
+         break;
+      }
+
+      case 0xD: {  /* SHRA_R.PH */
+         DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            assign(t0, binop(Iop_Sar32,
+                             binop(Iop_Add32,
+                                   unop(Iop_16Sto32,
+                                        unop(Iop_32to16,
+                                             getIReg(rt))),
+                                   binop(Iop_Shl32,
+                                         mkU32(0x1),
+                                         mkU8(rs - 1))),
+                             mkU8(rs)));
+            assign(t1, binop(Iop_Sar32,
+                             binop(Iop_Add32,
+                                   unop(Iop_16Sto32,
+                                        unop(Iop_32HIto16,
+                                             getIReg(rt))),
+                                   binop(Iop_Shl32,
+                                         mkU32(0x1),
+                                         mkU8(rs - 1))),
+                             mkU8(rs)));
+            putIReg(rd, binop(Iop_16HLto32,
+                              unop(Iop_32to16, mkexpr(t1)),
+                              unop(Iop_32to16, mkexpr(t0))));
+         }
+
+         break;
+      }
+
+      case 0xE: {  /* SHLLV_S.PH */
+         DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I32);
+         t12 = newTemp(Ity_I1);
+         t13 = newTemp(Ity_I1);
+         t14 = newTemp(Ity_I16);
+         t15 = newTemp(Ity_I16);
+         t16 = newTemp(Ity_I16);
+         t17 = newTemp(Ity_I16);
+
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
+
+         /* Shift lower 16 bits. */
+         assign(t2, binop(Iop_Shl32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         assign(t3, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0x00000000)));
+         assign(t4, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t2))),
+                          mkU32(0xffffffff)));
+         assign(t10, binop(Iop_And32,
+                           unop(Iop_1Sto32, mkexpr(t3)),
+                           unop(Iop_1Sto32, mkexpr(t4))));
+         assign(t5, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x00008000)),
+                          mkU8(15)));
+         assign(t12, binop(Iop_CmpEQ32,
+                           mkexpr(t5),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       mkexpr(t2),
+                                       mkU32(0x00008000)),
+                                 mkU8(15))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t10),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  IRExpr_ITE(mkexpr(t12),
+                                             getDSPControl(),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x400000)))
+                                 ));
+         assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t5),
+                                      mkU32(0x0)),
+                                mkU16(0x8000),
+                                mkU16(0x7fff)));
+         assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t10),
+                                      mkU32(0x0)),
+                                mkexpr(t14),
+                                IRExpr_ITE(mkexpr(t12),
+                                           unop(Iop_32to16,
+                                                mkexpr(t2)),
+                                           mkexpr(t14))));
+         /* Shift higher 16 bits. */
+         assign(t6, binop(Iop_Shl32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         assign(t7, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t6))),
+                          mkU32(0x00000000)));
+         assign(t8, binop(Iop_CmpNE32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, mkexpr(t6))),
+                          mkU32(0xffffffff)));
+         assign(t11, binop(Iop_And32,
+                           unop(Iop_1Sto32, mkexpr(t7)),
+                           unop(Iop_1Sto32, mkexpr(t8))));
+
+         assign(t9, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x80000000)),
+                          mkU8(31)));
+         assign(t13, binop(Iop_CmpEQ32,
+                           mkexpr(t9),
+                           binop(Iop_Shr32,
+                                 binop(Iop_And32,
+                                       mkexpr(t6),
+                                       mkU32(0x00008000)),
+                                 mkU8(15))));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t11),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  IRExpr_ITE(mkexpr(t13),
+                                             getDSPControl(),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x400000)))
+                                 ));
+
+         assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t9),
+                                      mkU32(0x0)),
+                                mkU16(0x8000),
+                                mkU16(0x7fff)));
+         assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
+                                      mkexpr(t11),
+                                      mkU32(0x0)),
+                                mkexpr(t16),
+                                IRExpr_ITE(mkexpr(t13),
+                                           unop(Iop_32to16,
+                                                mkexpr(t6)),
+                                           mkexpr(t16))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
+         break;
+      }
+
+      case 0xF: {  /* SHRAV_R.PH */
+         DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
+         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
+         assign(t2, unop(Iop_32to8,
+                         binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
+
+         assign(t3, binop(Iop_Sar32,
+                          binop(Iop_Add32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16, getIReg(rt))),
+                                binop(Iop_Shl32,
+                                      mkU32(0x1),
+                                      mkexpr(t2))),
+                          unop(Iop_32to8, mkexpr(t0))));
+         assign(t4, binop(Iop_Sar32,
+                          binop(Iop_Add32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rt))),
+                                binop(Iop_Shl32,
+                                      mkU32(0x1),
+                                      mkexpr(t2))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           IRExpr_ITE(mkexpr(t1),
+                                      unop(Iop_32HIto16,
+                                           getIReg(rt)),
+                                      unop(Iop_32to16,
+                                           mkexpr(t4))),
+                           IRExpr_ITE(mkexpr(t1),
+                                      unop(Iop_32to16, getIReg(rt)),
+                                      unop(Iop_32to16,
+                                           mkexpr(t3)))));
+         break;
+      }
+
+      case 0x14: {  /* SHLL_S.W */
+         DIP("shll_s.w r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            /* t0-bits that will be discarded, sign extended to
+               32bits. */
+            assign(t0, binop(Iop_Sar32,
+                             binop(Iop_And32,
+                                   getIReg(rt),
+                                   binop(Iop_Sar32,
+                                         mkU32(0x80000000),
+                                         mkU8(rs - 1))),
+                             mkU8(32 - rs)));
+
+            assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        binop(Iop_And32,
+                                              getIReg(rt),
+                                              mkU32(0x80000000)),
+                                        mkU32(0x0)),
+                                  mkU32(0x7fffffff),
+                                  mkU32(0x80000000)));
+
+            assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
+            assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        binop(Iop_And32,
+                                              getIReg(rt),
+                                              mkU32(0x80000000)),
+                                        binop(Iop_And32,
+                                              mkexpr(t2),
+                                              mkU32(0x80000000))),
+                                  mkexpr(t2),
+                                  mkexpr(t1)));
+
+            assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t0),
+                                        mkU32(0x0)),
+                                  IRExpr_ITE(binop(Iop_CmpNE32,
+                                                   mkexpr(t0),
+                                                   mkU32(0xffffffff)
+                                                  ),
+                                             mkexpr(t1),
+                                             mkexpr(t3)),
+                                  mkexpr(t3)));
+            assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t0),
+                                        mkU32(0xffffffff)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                           mkexpr(t0),
+                                           mkU32(0x0)),
+                                     mkexpr(t5),
+                                     getDSPControl()));
+            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                           binop(Iop_And32,
+                                                 getIReg(rt),
+                                                 mkU32(0x80000000)),
+                                           binop(Iop_And32,
+                                                 mkexpr(t2),
+                                                 mkU32(0x80000000))
+                                          ),
+                                     getDSPControl(),
+                                     binop(Iop_Or32,
+                                           getDSPControl(),
+                                           mkU32(0x400000))));
+            putIReg(rd, mkexpr(t4));
+         }
+
+         break;
+      }
+
+      case 0x15: {  /* SHRA_R.W */
+         DIP("shra_r.w r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+
+         if (0 == rs) {
+            putIReg(rd, getIReg(rt));
+         } else {
+            putIReg(rd, binop(Iop_Add32,
+                              binop(Iop_Sar32,
+                                    getIReg(rt), mkU8(rs)),
+                              binop(Iop_Shr32,
+                                    binop(Iop_And32,
+                                          getIReg(rt),
+                                          binop(Iop_Shl32,
+                                                mkU32(0x1),
+                                                mkU8(rs - 1))),
+                                    mkU8(rs - 1))));
+         }
+
+         break;
+      }
+
+      case 0x16: {  /* SHLLV_S.W */
+         DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I1);
+         t5 = newTemp(Ity_I1);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I32);
+
+         /* Check if shift amount is zero. */
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
+         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
+
+         /* t2 = sign of the input value. */
+         assign(t2, binop(Iop_Shr32,
+                          binop(Iop_And32,
+                                getIReg(rt),
+                                mkU32(0x80000000)),
+                          mkU8(31)));
+         /* Shift left input value and check for overflow. */
+         assign(t3, binop(Iop_Shl64,
+                          unop(Iop_32Sto64, getIReg(rt)),
+                          unop(Iop_32to8, mkexpr(t0))));
+         assign(t4, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32, mkexpr(t3)),
+                          mkU32(0x00000000)));
+         assign(t5, binop(Iop_CmpNE32,
+                          unop(Iop_64HIto32, mkexpr(t3)),
+                          mkU32(0xffffffff)));
+         assign(t6, binop(Iop_And32,
+                          unop(Iop_1Uto32, mkexpr(t4)),
+                          unop(Iop_1Uto32, mkexpr(t5))));
+         assign(t7, binop(Iop_CmpEQ32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      getIReg(rt),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t3)),
+                                      mkU32(0x80000000)),
+                                mkU8(31))));
+
+         putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x400000)),
+                                  IRExpr_ITE(mkexpr(t7),
+                                             getDSPControl(),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x400000)))
+                                 ));
+
+         assign(t8, IRExpr_ITE(unop(Iop_32to1,
+                                    mkexpr(t2)),
+                               mkU32(0x80000000),
+                               mkU32(0x7fffffff)));
+         putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
+                                IRExpr_ITE(unop(Iop_32to1,
+                                                mkexpr(t2)),
+                                           mkU32(0x80000000),
+                                           mkU32(0x7fffffff)),
+                                IRExpr_ITE(mkexpr(t7),
+                                           unop(Iop_64to32,
+                                                mkexpr(t3)),
+                                           mkexpr(t8))));
+         break;
+      }
+
+      case 0x17: {  /* SHRAV_R.W */
+         DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
+         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
+         assign(t2, unop(Iop_32to8,
+                         binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
+
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                getIReg(rt),
+                                binop(Iop_Sar32,
+                                      binop(Iop_Add32,
+                                            binop(Iop_Sar32,
+                                                  getIReg(rt),
+                                                  mkexpr(t2)),
+                                            mkU32(0x1)),
+                                      mkU8(1))));
+         break;
+      }
+
+      case 0x19: {  /* SHRL.PH */
+         DIP("shrl.ph r%u, r%u, %u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         assign(t0, binop(Iop_Shr32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU8(rs)));
+         assign(t1, binop(Iop_Shr32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU8(rs)));
+         putIReg(rd, binop(Iop_16HLto32,
+                           unop(Iop_32to16, mkexpr(t1)),
+                           unop(Iop_32to16, mkexpr(t0))));
+         break;
+      }
+
+      case 0x1B: {  /* SHRLV.PH */
+         DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I16);
+         t5 = newTemp(Ity_I16);
+
+         /* Get shift amount from lower 5 bits of rs
+            and check if it is zero. */
+         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
+         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
+
+         assign(t2, binop(Iop_Shr32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+         assign(t3, binop(Iop_Shr32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          unop(Iop_32to8, mkexpr(t0))));
+
+         assign(t4, IRExpr_ITE(mkexpr(t1),
+                               unop(Iop_32HIto16, getIReg(rt)),
+                               unop(Iop_32to16, mkexpr(t3))));
+         assign(t5, IRExpr_ITE(mkexpr(t1),
+                               unop(Iop_32to16, getIReg(rt)),
+                               unop(Iop_32to16, mkexpr(t2))));
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_ADDUH_QB( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
+   UInt   rs, rt, rd, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x00: {  /* ADDUH.QB */
+         DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));
+
+         putIReg(rd, mkexpr(t0));
+         break;
+      }
+
+      case 0x1: {  /* SUBUH.QB */
+         DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+
+         assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));
+
+         putIReg(rd, mkexpr(t0));
+         break;
+      }
+
+      case 0x02: {  /* ADDUH_R.QB */
+         DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I8);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I8);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I8);
+         t9 = newTemp(Ity_I32);
+         t10 = newTemp(Ity_I32);
+         t11 = newTemp(Ity_I8);
+
+         /* Extract input bytes, add values, add 1 and half the
+            result. */
+         assign(t0, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rs)))));
+         assign(t1, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t2, unop(Iop_16to8,
+                         unop(Iop_32to16,
+                              binop(Iop_Shr32,
+                                    binop(Iop_Add32,
+                                          binop(Iop_Add32,
+                                                mkexpr(t0),
+                                                mkexpr(t1)),
+                                          mkU32(0x00000001)),
+                                    mkU8(0x01)))));
+
+         assign(t3, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rs)))));
+         assign(t4, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t5, unop(Iop_16to8,
+                         unop(Iop_32to16,
+                              binop(Iop_Shr32,
+                                    binop(Iop_Add32,
+                                          binop(Iop_Add32,
+                                                mkexpr(t3),
+                                                mkexpr(t4)),
+                                          mkU32(0x00000001)),
+                                    mkU8(0x01)))));
+
+         assign(t6, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rs)))));
+         assign(t7, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t8, unop(Iop_16to8,
+                         unop(Iop_32to16,
+                              binop(Iop_Shr32,
+                                    binop(Iop_Add32,
+                                          binop(Iop_Add32,
+                                                mkexpr(t7),
+                                                mkexpr(t6)),
+                                          mkU32(0x00000001)),
+                                    mkU8(0x01)))));
+
+         assign(t9, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32HIto16, getIReg(rs)))));
+         assign(t10, unop(Iop_8Uto32,
+                          unop(Iop_16HIto8,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t11, unop(Iop_16to8,
+                          unop(Iop_32to16,
+                               binop(Iop_Shr32,
+                                     binop(Iop_Add32,
+                                           binop(Iop_Add32,
+                                                 mkexpr(t9),
+                                                 mkexpr(t10)),
+                                           mkU32(0x00000001)),
+                                     mkU8(0x01)))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           binop(Iop_8HLto16,
+                                 mkexpr(t11), mkexpr(t8)),
+                           binop(Iop_8HLto16,
+                                 mkexpr(t5), mkexpr(t2))));
+         break;
+      }
+
+      case 0x3: {  /* SUBUH_R.QB */
+         DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I8);
+         t10 = newTemp(Ity_I8);
+         t11 = newTemp(Ity_I8);
+         t12 = newTemp(Ity_I8);
+
+         /* Extract each byte of rs and rt. */
+         assign(t1, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rs)))));
+         assign(t2, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rs)))));
+         assign(t3, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rs)))));
+         assign(t4, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32HIto16, getIReg(rs)))));
+
+         assign(t5, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t6, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32to16, getIReg(rt)))));
+         assign(t7, unop(Iop_8Uto32,
+                         unop(Iop_16to8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t8, unop(Iop_8Uto32,
+                         unop(Iop_16HIto8,
+                              unop(Iop_32HIto16, getIReg(rt)))));
+
+         /* Add 1 to each resulting byte and half the results. */
+         assign(t9, unop(Iop_16to8,
+                         unop(Iop_32to16,
+                              binop(Iop_Shr32,
+                                    binop(Iop_Add32,
+                                          binop(Iop_Sub32,
+                                                mkexpr(t1),
+                                                mkexpr(t5)),
+                                          mkU32(0x00000001)),
+                                    mkU8(0x01)))));
+         assign(t10, unop(Iop_16to8,
+                          unop(Iop_32to16,
+                               binop(Iop_Shr32,
+                                     binop(Iop_Add32,
+                                           binop(Iop_Sub32,
+                                                 mkexpr(t2),
+                                                 mkexpr(t6)),
+                                           mkU32(0x00000001)),
+                                     mkU8(0x01)))));
+         assign(t11, unop(Iop_16to8,
+                          unop(Iop_32to16,
+                               binop(Iop_Shr32,
+                                     binop(Iop_Add32,
+                                           binop(Iop_Sub32,
+                                                 mkexpr(t3),
+                                                 mkexpr(t7)),
+                                           mkU32(0x00000001)),
+                                     mkU8(0x01)))));
+         assign(t12, unop(Iop_16to8,
+                          unop(Iop_32to16,
+                               binop(Iop_Shr32,
+                                     binop(Iop_Add32,
+                                           binop(Iop_Sub32,
+                                                 mkexpr(t4),
+                                                 mkexpr(t8)),
+                                           mkU32(0x00000001)),
+                                     mkU8(0x01)))));
+
+         putIReg(rd, binop(Iop_16HLto32,
+                           binop(Iop_8HLto16,
+                                 mkexpr(t12), mkexpr(t11)),
+                           binop(Iop_8HLto16,
+                                 mkexpr(t10), mkexpr(t9))));
+         break;
+      }
+
+      case 0x8: {  /* ADDQH.PH */
+         DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I16);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I16);
+
+         /* Add lower halfs of rs and rt
+            and right shift the result by 1. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+         assign(t1, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     mkexpr(t0),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+         /* Add higher halfs of rs and rt
+            and right shift the result by 1. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t3, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     mkexpr(t2),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
+         break;
+      }
+
+      case 0x9: {  /* SUBQH.PH */
+         DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+
+         putIReg(rd, binop(Iop_HSub16Sx2,
+                           getIReg(rs), getIReg(rt)));
+         break;
+      }
+
+      case 0xA: {/* ADDQH_R.PH */
+         DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I16);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I16);
+
+         /* Add lower halfs of rs and rt, add 1
+            and right shift the result by 1. */
+         assign(t0, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+         assign(t1, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     binop(Iop_Add32,
+                                           mkexpr(t0),
+                                           mkU32(0x1)),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+         /* Add higher halfs of rs and rt, add 1
+            and right shift the result by 1. */
+         assign(t2, binop(Iop_Add32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t3, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     binop(Iop_Add32,
+                                           mkexpr(t2),
+                                           mkU32(0x1)),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
+         break;
+      }
+
+      case 0xB: {  /* SUBQH_R.PH */
+         DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I16);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I16);
+
+         /* Sub lower halfs of rs and rt, add 1
+            and right shift the result by 1. */
+         assign(t0, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+         assign(t1, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     binop(Iop_Add32,
+                                           mkexpr(t0),
+                                           mkU32(0x1)),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+         /* Sub higher halfs of rs and rt, add 1
+            and right shift the result by 1. */
+         assign(t2, binop(Iop_Sub32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt)))));
+         assign(t3, unop(Iop_32to16,
+                         binop(Iop_Shr32,
+                               binop(Iop_And32,
+                                     binop(Iop_Add32,
+                                           mkexpr(t2),
+                                           mkU32(0x1)),
+                                     mkU32(0x0001fffe)),
+                               mkU8(0x1))));
+
+         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
+         break;
+      }
+
+      case 0xC: {  /* MUL.PH */
+         DIP("mul.ph r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_16Sto32,
+                           unop(Iop_32HIto16, getIReg(rs))),
+                      unop(Iop_16Sto32,
+                           unop(Iop_32HIto16, getIReg(rt)))));
+         /* DSP Control flag. */
+         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
+                                       binop(Iop_CmpLE32S,
+                                             mkexpr(t0),
+                                             mkU32(0x7FFF))),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00200000)),
+                                  IRExpr_ITE(binop(Iop_CmpLT32S,
+                                             mkexpr(t0),
+                                             mkU32(0xFFFF8000)
+                                                  ),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl())));
+
+         assign(t1,
+                binop(Iop_Mul32,
+                      unop(Iop_16Sto32,
+                           unop(Iop_32to16, getIReg(rs))),
+                      unop(Iop_16Sto32,
+                           unop(Iop_32to16, getIReg(rt)))));
+         /* DSP Control flag. */
+         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
+                                       binop(Iop_CmpLE32S,
+                                             mkexpr(t1),
+                                             mkU32(0x7FFF))),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00200000)),
+                                  IRExpr_ITE(binop(Iop_CmpLT32S,
+                                             mkexpr(t1),
+                                             mkU32(0xFFFF8000)
+                                                  ),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl())));
+
+         assign(t2, binop(Iop_16HLto32,
+                          unop(Iop_32to16, mkexpr(t0)),
+                          unop(Iop_32to16, mkexpr(t1))));
+         putIReg(rd, mkexpr(t2));
+         break;
+      }
+
+      case 0xE: {  /* MUL_S.PH */
+         DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+
+         /* t0 - signed intermediate result. */
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_16Sto32,
+                           unop(Iop_32HIto16, getIReg(rs))),
+                      unop(Iop_16Sto32,
+                           unop(Iop_32HIto16, getIReg(rt)))));
+
+         assign(t1,
+                IRExpr_ITE(unop(Iop_Not1,
+                                binop(Iop_CmpLE32S,
+                                      mkexpr(t0),
+                                      mkU32(0x7FFF))),
+                           mkU32(0x00007FFF),
+                           IRExpr_ITE(binop(Iop_CmpLT32S,
+                                            mkexpr(t0),
+                                            mkU32(0xFFFF8000)),
+                                      mkU32(0xFFFF8000),
+                                      mkexpr(t0))));
+
+         /* DSP Control flag. */
+         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
+                                       binop(Iop_CmpLE32S,
+                                             mkexpr(t0),
+                                             mkU32(0x7FFF))),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00200000)),
+                                  IRExpr_ITE(binop(Iop_CmpLT32S,
+                                             mkexpr(t0),
+                                             mkU32(0xFFFF8000)
+                                                  ),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl())));
+
+         /* t2 - signed intermediate result. */
+         assign(t2, binop(Iop_Mul32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt)))));
+
+         assign(t3, IRExpr_ITE(unop(Iop_Not1,
+                                    binop(Iop_CmpLE32S,
+                                          mkexpr(t2),
+                                          mkU32(0x7FFF))),
+                               mkU32(0x00007FFF),
+                               IRExpr_ITE(binop(Iop_CmpLT32S,
+                                                mkexpr(t2),
+                                                mkU32(0xFFFF8000)),
+                                          mkU32(0xFFFF8000),
+                                          mkexpr(t2))));
+
+         /* DSP Control flag. */
+         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
+                                       binop(Iop_CmpLE32S,
+                                             mkexpr(t2),
+                                             mkU32(0x7FFF))),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        mkU32(0x00200000)),
+                                  IRExpr_ITE(binop(Iop_CmpLT32S,
+                                             mkexpr(t2),
+                                             mkU32(0xFFFF8000)
+                                                  ),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl())));
+
+         assign(t4, binop(Iop_16HLto32,
+                          unop(Iop_32to16, mkexpr(t1)),
+                          unop(Iop_32to16, mkexpr(t3))));
+         putIReg(rd, mkexpr(t4));
+         break;
+      }
+
+      case 0x10: {  /* ADDQH.W */
+         DIP("addqh.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+
+         assign(t0, binop(Iop_Add64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+         assign(t1, binop(Iop_And64,
+                          mkexpr(t0),
+                          mkU64(0x00000001fffffffeULL)));
+         putIReg(rd, unop(Iop_64to32,
+                          binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
+         break;
+      }
+
+      case 0x11: {  /* SUBQH.W */
+         DIP("subqh.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+
+         assign(t0, binop(Iop_Sub64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+         assign(t1, binop(Iop_And64,
+                          mkexpr(t0),
+                          mkU64(0x00000001fffffffeULL)));
+         putIReg(rd, unop(Iop_64to32,
+                          binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
+         break;
+      }
+
+      case 0x12: {  /* ADDQH_R.W */
+         DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0, binop(Iop_Add64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+         assign(t1, binop(Iop_Add64,
+                          mkexpr(t0),
+                          mkU64(0x0000000000000001ULL)));
+         assign(t2, binop(Iop_And64,
+                          mkexpr(t1),
+                          mkU64(0x00000001fffffffeULL)));
+         putIReg(rd, unop(Iop_64to32,
+                          binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
+         break;
+      }
+
+      case 0x13: {  /* SUBQH_R.W */
+         DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0, binop(Iop_Sub64,
+                          unop(Iop_32Sto64, getIReg(rs)),
+                          unop(Iop_32Sto64, getIReg(rt))));
+         assign(t1, binop(Iop_Add64,
+                          mkexpr(t0),
+                          mkU64(0x0000000000000001ULL)));
+         assign(t2, binop(Iop_And64,
+                          mkexpr(t1),
+                          mkU64(0x00000001fffffffeULL)));
+         putIReg(rd, unop(Iop_64to32,
+                          binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
+         break;
+      }
+
+      case 0x16: {  /* MULQ_S.W */
+         DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t0, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                getIReg(rt), getIReg(rs)),
+                          mkU8(0x1)));
+         assign(t1, binop(Iop_CmpEQ32,
+                          getIReg(rt), mkU32(0x80000000)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          getIReg(rs), mkU32(0x80000000)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  IRExpr_ITE(mkexpr(t2),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(mkexpr(t2),
+                                           mkU32(0x7fffffff),
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t0))),
+                                unop(Iop_64HIto32, mkexpr(t0))));
+         break;
+      }
+
+      case 0x17: {  /* MULQ_RS.W */
+         DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I1);
+         t2 = newTemp(Ity_I1);
+
+         assign(t0, binop(Iop_Add64,
+                          binop(Iop_Shl64,
+                                binop(Iop_MullS32,
+                                      getIReg(rt),
+                                      getIReg(rs)),
+                                mkU8(0x1)),
+                          mkU64(0x0000000080000000ULL)));
+         assign(t1,
+                binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
+         assign(t2,
+                binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
+         putDSPControl(IRExpr_ITE(mkexpr(t1),
+                                  IRExpr_ITE(mkexpr(t2),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   mkU32(0x00200000)
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         putIReg(rd, IRExpr_ITE(mkexpr(t1),
+                                IRExpr_ITE(mkexpr(t2),
+                                           mkU32(0x7fffffff),
+                                           unop(Iop_64HIto32,
+                                                mkexpr(t0))),
+                                unop(Iop_64HIto32, mkexpr(t0))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_DPAW_PH( UInt cins )
+{
+   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10;
+   UInt   rs, rt, sa, ac;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   sa = get_sa(cins);
+   ac = get_acNo(cins);
+
+   switch (sa) {
+      case 0x0: {  /* DPA.W.PH */
+         DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t1,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t2,
+                binop(Iop_Add64,
+                      getAcc(ac),
+                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, mkexpr(t2));
+         break;
+      }
+
+      case 0x1: {  /* DPS.W.PH */
+         DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t1,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t2,
+                binop(Iop_Sub64,
+                      getAcc(ac),
+                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, mkexpr(t2));
+         break;
+      }
+
+      case 0x2: {  /* MULSA.W.PH */
+         DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+
+         assign(t4, getAcc(ac));
+         assign(t0, binop(Iop_Mul32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32to16, getIReg(rs)))));
+         assign(t1, binop(Iop_Mul32,
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          unop(Iop_16Sto32,
+                               unop(Iop_32HIto16, getIReg(rs)))));
+         assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
+         putAcc(ac, binop(Iop_Add64,
+                          mkexpr(t4),
+                          unop(Iop_32Sto64, mkexpr(t2))));
+         break;
+      }
+
+      case 0x3: {  /* DPAU.H.QBL */
+         DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t1,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t2,
+                unop(Iop_32Uto64,
+                     binop(Iop_Add32,
+                           mkexpr(t0),
+                           mkexpr(t1))));
+         assign(t3,
+                binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0x4: {  /* DPAQ_S.W.PH */
+         DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16, getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16, getIReg(rt)))
+                               ),
+                          mkU8(0x1)));
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t8,
+                IRExpr_ITE(mkexpr(t6),
+                           IRExpr_ITE(mkexpr(t7),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t5)),
+                           mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  IRExpr_ITE(mkexpr(t7),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t9, binop(Iop_Add64,
+                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
+                          mkexpr(t0)));
+         putAcc(ac, mkexpr(t9));
+         break;
+      }
+
+      case 0x5: {  /* DPSQ_S.W.PH */
+         DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5,
+                binop(Iop_Shl64,
+                      binop(Iop_MullS32,
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32to16, getIReg(rs))),
+                            unop(Iop_16Sto32,
+                                 unop(Iop_32to16, getIReg(rt)))),
+                      mkU8(0x1)));
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t8,
+                IRExpr_ITE(mkexpr(t6),
+                           IRExpr_ITE(mkexpr(t7),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t5)),
+                           mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  IRExpr_ITE(mkexpr(t7),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t9,
+                binop(Iop_Sub64,
+                      mkexpr(t0),
+                      binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
+         putAcc(ac, mkexpr(t9));
+         break;
+      }
+
+      case 0x6: {  /* MULSAQ_S.W.PH */
+         DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I64);
+         t8 = newTemp(Ity_I32);
+         t9 = newTemp(Ity_I32);
+
+         assign(t0, unop(Iop_16Sto32,
+                         unop(Iop_32HIto16, getIReg(rs))));
+         assign(t1, unop(Iop_16Sto32,
+                         unop(Iop_32HIto16, getIReg(rt))));
+
+         assign(t8, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     unop(Iop_16Uto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rs))),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     unop(Iop_16Uto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rt))),
+                                     mkU32(0x8000)))));
+         /* DSPControl_outflag:16+acc <- 1 */
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t8),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x00010000),
+                                              mkU8(ac))),
+                                  getDSPControl()));
+
+         /* tempB_31..0 */
+         assign(t2,
+                IRExpr_ITE(binop(Iop_CmpNE32,
+                                 mkexpr(t8), mkU32(0x0)),
+                           mkU32(0x7FFFFFFF),
+                           binop(Iop_Shl32,
+                                 binop(Iop_Mul32,
+                                       mkexpr(t0), mkexpr(t1)),
+                                 mkU8(1))));
+
+         assign(t3, unop(Iop_16Sto32,
+                         unop(Iop_32to16, getIReg(rs))));
+         assign(t4, unop(Iop_16Sto32,
+                         unop(Iop_32to16, getIReg(rt))));
+
+         assign(t9, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     unop(Iop_16Uto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rs))),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     unop(Iop_16Uto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rt))),
+                                     mkU32(0x8000)))));
+         /* DSPControl_outflag:16+acc <- 1 */
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        mkexpr(t9),
+                                        mkU32(0x0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x00010000),
+                                              mkU8(ac))),
+                                  getDSPControl()));
+         /* tempA_31..0 */
+         assign(t5,
+                IRExpr_ITE(binop(Iop_CmpNE32,
+                                 mkexpr(t9),
+                                 mkU32(0x0)),
+                           mkU32(0x7FFFFFFF),
+                           binop(Iop_Shl32,
+                                 binop(Iop_Mul32,
+                                       mkexpr(t3),
+                                       mkexpr(t4)),
+                                 mkU8(1))));
+         /* dotp_63..0 */
+         assign(t6,
+                binop(Iop_Sub64,
+                      unop(Iop_32Sto64, mkexpr(t2)),
+                      unop(Iop_32Sto64, mkexpr(t5))));
+         /* tempC_63..0 */
+         assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));
+
+         putAcc(ac, mkexpr(t7));
+         break;
+      }
+
+      case 0x7: {  /* DPAU.H.QBR */
+         DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t1,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t2, unop(Iop_32Uto64,
+                         binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
+         assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0x8: {  /* DPAX.W.PH */
+         DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t1,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t2,
+                binop(Iop_Add64,
+                      getAcc(ac),
+                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, mkexpr(t2));
+         break;
+      }
+
+      case 0x9: {  /* DPSX.W.PH */
+         DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I64);
+
+         assign(t0,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t1,
+                unop(Iop_32Sto64,
+                     binop(Iop_Mul32,
+                           unop(Iop_16Sto32,
+                                unop(Iop_32to16, getIReg(rs))),
+                           unop(Iop_16Sto32,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t2,
+                binop(Iop_Sub64,
+                      getAcc(ac),
+                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, mkexpr(t2));
+         break;
+      }
+
+      case 0xB: {  /* DPSU.H.QBL */
+         DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t1,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32HIto16, getIReg(rt))))));
+         assign(t2,
+                unop(Iop_32Uto64,
+                     binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
+         assign(t3,
+                binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
+         putAcc(ac, mkexpr(t3));
+         break;
+      }
+
+      case 0xC: {  /* DPAQ_SA.L.W */
+         DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I64);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I1);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                getIReg(rs), getIReg(rt)),
+                          mkU8(0x1)));
+
+         assign(t2, binop(Iop_CmpEQ32,
+                          getIReg(rs),
+                          mkU32(0x80000000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          getIReg(rt),
+                          mkU32(0x80000000)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x7fffffffffffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5, binop(Iop_Add64,
+                          unop(Iop_32Uto64,
+                               unop(Iop_64to32, mkexpr(t0))),
+                          unop(Iop_32Uto64,
+                               unop(Iop_64to32, mkexpr(t4)))));
+         assign(t6,
+                binop(Iop_Add64,
+                      binop(Iop_Add64,
+                            unop(Iop_32Sto64,
+                                 unop(Iop_64HIto32, mkexpr(t0))),
+                            unop(Iop_32Sto64,
+                                 unop(Iop_64HIto32, mkexpr(t4)))),
+                      unop(Iop_32Uto64,
+                           binop(Iop_And32,
+                                 unop(Iop_64HIto32, mkexpr(t5)),
+                                 mkU32(0x1)))));
+         assign(t7, binop(Iop_32HLto64,
+                          unop(Iop_64to32, mkexpr(t6)),
+                          unop(Iop_64to32, mkexpr(t5))));
+         assign(t8, binop(Iop_CmpEQ32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t6)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t6)),
+                                mkU32(0x00000001))));
+         assign(t9, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32,
+                                     mkexpr(t6)),
+                                mkU32(0x00000001)),
+                          mkU32(0x1)));
+         putDSPControl(IRExpr_ITE(mkexpr(t8),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         putAcc(ac,
+                IRExpr_ITE(mkexpr(t8),
+                           mkexpr(t7),
+                           IRExpr_ITE(mkexpr(t9),
+                                      mkU64(0x8000000000000000ULL),
+                                      mkU64(0x7fffffffffffffffULL)))
+               );
+         break;
+      }
+
+      case 0xD: {  /* DPSQ_SA.L.W */
+         DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I64);
+         t7 = newTemp(Ity_I64);
+         t8 = newTemp(Ity_I1);
+         t9 = newTemp(Ity_I1);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                getIReg(rs), getIReg(rt)),
+                          mkU8(0x1)));
+
+         assign(t2, binop(Iop_CmpEQ32,
+                          getIReg(rs),
+                          mkU32(0x80000000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          getIReg(rt),
+                          mkU32(0x80000000)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x7fffffffffffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5, binop(Iop_Sub64,
+                          unop(Iop_32Uto64,
+                               unop(Iop_64to32, mkexpr(t0))),
+                          unop(Iop_32Uto64,
+                               unop(Iop_64to32, mkexpr(t4)))));
+         assign(t6, binop(Iop_Sub64,
+                          binop(Iop_Add64,
+                                unop(Iop_32Sto64,
+                                     unop(Iop_64HIto32, mkexpr(t0))
+                                    ),
+                                unop(Iop_32Sto64,
+                                     unop(Iop_1Sto32,
+                                          binop(Iop_CmpLT32U,
+                                                unop(Iop_64to32,
+                                                      mkexpr(t0)),
+                                                unop(Iop_64to32,
+                                                      mkexpr(t4)))))),
+                          unop(Iop_32Sto64,
+                               unop(Iop_64HIto32, mkexpr(t4)))));
+         assign(t7, binop(Iop_32HLto64,
+                          unop(Iop_64to32, mkexpr(t6)),
+                          unop(Iop_64to32, mkexpr(t5))));
+         assign(t8, binop(Iop_CmpEQ32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t6)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t6)),
+                                mkU32(0x00000001))));
+         assign(t9, binop(Iop_CmpEQ32,
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t6)),
+                                mkU32(0x00000001)),
+                          mkU32(0x1)));
+         putDSPControl(IRExpr_ITE(mkexpr(t8),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         putAcc(ac,
+                IRExpr_ITE(mkexpr(t8),
+                           mkexpr(t7),
+                           IRExpr_ITE(mkexpr(t9),
+                                      mkU64(0x8000000000000000ULL),
+                                      mkU64(0x7fffffffffffffffULL)))
+               );
+         break;
+      }
+
+      case 0xF: {  /* DPSU.H.QBR */
+         DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I64);
+         t3 = newTemp(Ity_I64);
+
+         assign(t0,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16HIto8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t1,
+                binop(Iop_Mul32,
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rs)))),
+                      unop(Iop_8Uto32,
+                           unop(Iop_16to8,
+                                unop(Iop_32to16, getIReg(rt))))));
+         assign(t2, unop(Iop_32Uto64,
+                         binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
+         assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
+         putAcc(ac, mkexpr(t3));
+
+         break;
+      }
+
+      case 0x10: {  /* MAQ_SA.W.PHL */
+         DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+         assign(t1, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl register.
+         */
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         /* Add intermediate product and value in the
+            accumulator. */
+         assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
+
+         /* Compare bits 31 and 32 of the value in t5. */
+         assign(t6, binop(Iop_CmpEQ32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t5)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t5)),
+                                mkU32(1))));
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         assign(t7,
+                IRExpr_ITE(mkexpr(t6),
+                           mkexpr(t5),
+                           IRExpr_ITE(binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                        mkexpr(t5)),
+                                                  mkU32(1)),
+                                            mkU32(0x0)),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkU64(0xffffffff80000000ULL)))
+               );
+         putAcc(ac, mkexpr(t7));
+         break;
+      }
+
+      case 0x12: {  /* MAQ_SA.W.PHR */
+         DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+         assign(t1, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl
+            register. */
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+         /* Add intermediate product and value in the
+            accumulator. */
+         assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
+
+         /* Compare bits 31 and 32 of the value in t5. */
+         assign(t6, binop(Iop_CmpEQ32,
+                          binop(Iop_Shr32,
+                                binop(Iop_And32,
+                                      unop(Iop_64to32, mkexpr(t5)),
+                                      mkU32(0x80000000)),
+                                mkU8(31)),
+                          binop(Iop_And32,
+                                unop(Iop_64HIto32, mkexpr(t5)),
+                                mkU32(1))));
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         assign(t7,
+                IRExpr_ITE(mkexpr(t6),
+                           mkexpr(t5),
+                           IRExpr_ITE(binop(Iop_CmpEQ32,
+                                            binop(Iop_And32,
+                                                  unop(Iop_64HIto32,
+                                                        mkexpr(t5)),
+                                                  mkU32(1)),
+                                            mkU32(0x0)),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkU64(0xffffffff80000000ULL)))
+               );
+         putAcc(ac, mkexpr(t7));
+         break;
+      }
+
+      case 0x14: {  /* MAQ_S.W.PHL */
+         DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I64);
+
+         assign(t5, getAcc(ac));
+
+         assign(t0, unop(Iop_16Sto32,
+                         unop(Iop_32HIto16, getIReg(rs))));
+         assign(t1, unop(Iop_16Sto32,
+                         unop(Iop_32HIto16, getIReg(rt))));
+
+         assign(t2, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t1),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000)))));
+
+         assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+
+         assign(t4, unop(Iop_64to32,
+                         binop(Iop_MullS32,
+                               mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Add64,
+                                     unop(Iop_32Sto64,
+                                          binop(Iop_Shl32,
+                                                mkexpr(t4),
+                                                mkU8(0x1))),
+                                     mkexpr(t5)),
+                               binop(Iop_Add64,
+                                     mkexpr(t5),
+                                     unop(Iop_32Sto64,
+                                          mkU32(0x7fffffff)))));
+         break;
+      }
+
+      case 0x16: {  /* MAQ_S.W.PHR */
+         DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I32);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I64);
+
+         assign(t5, getAcc(ac));
+
+         assign(t0, unop(Iop_16Sto32,
+                         unop(Iop_32to16, getIReg(rs))));
+         assign(t1, unop(Iop_16Sto32,
+                         unop(Iop_32to16, getIReg(rt))));
+
+         assign(t2, binop(Iop_And32,
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000))),
+                          unop(Iop_1Sto32,
+                               binop(Iop_CmpEQ32,
+                                     binop(Iop_And32,
+                                           mkexpr(t1),
+                                           mkU32(0xffff)),
+                                     mkU32(0x8000)))));
+
+         assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t3),
+                                  getDSPControl(),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+
+         assign(t4, unop(Iop_64to32,
+                         binop(Iop_MullS32,
+                               mkexpr(t0), mkexpr(t1))));
+         putAcc(ac, IRExpr_ITE(mkexpr(t3),
+                               binop(Iop_Add64,
+                                     unop(Iop_32Sto64,
+                                          binop(Iop_Shl32,
+                                                mkexpr(t4),
+                                                mkU8(0x1))),
+                                     mkexpr(t5)),
+                               binop(Iop_Add64,
+                                     mkexpr(t5),
+                                     unop(Iop_32Sto64,
+                                          mkU32(0x7fffffff)))));
+         break;
+      }
+
+      case 0x18: {  /* DPAQX_S.W.PH */
+         DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16))),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t8,
+                IRExpr_ITE(mkexpr(t6),
+                           IRExpr_ITE(mkexpr(t7),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t5)),
+                           mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  IRExpr_ITE(mkexpr(t7),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t9, binop(Iop_Add64,
+                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
+                          mkexpr(t0)));
+         putAcc(ac, mkexpr(t9));
+         break;
+      }
+
+      case 0x19: {  /* DPSQX_S.W.PH */
+         DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+
+         assign(t0, getAcc(ac));
+
+         assign(t1, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t4,
+                IRExpr_ITE(mkexpr(t2),
+                           IRExpr_ITE(mkexpr(t3),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t1)),
+                           mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t2),
+                                  IRExpr_ITE(mkexpr(t3),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t5, binop(Iop_Shl64,
+                          binop(Iop_MullS32,
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32to16,
+                                          getIReg(rs))),
+                                unop(Iop_16Sto32,
+                                     unop(Iop_32HIto16,
+                                          getIReg(rt)))),
+                          mkU8(0x1)));
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+         assign(t8,
+                IRExpr_ITE(mkexpr(t6),
+                           IRExpr_ITE(mkexpr(t7),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t5)),
+                           mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(mkexpr(t6),
+                                  IRExpr_ITE(mkexpr(t7),
+                                             binop(Iop_Or32,
+                                                   getDSPControl(),
+                                                   binop(Iop_Shl32,
+                                                         mkU32(0x1),
+                                                         mkU8(ac + 16)
+                                                        )
+                                                  ),
+                                             getDSPControl()),
+                                  getDSPControl()));
+
+         assign(t9, binop(Iop_Sub64,
+                          mkexpr(t0),
+                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
+         putAcc(ac, mkexpr(t9));
+         break;
+      }
+
+      case 0x1A: {  /* DPAQX_SA.W.PH */
+         DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+         /* Calculate the first cross dot product and saturate if
+            needed. */
+         assign(t1, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl
+            register. */
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t2)),
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t3))),
+                                     mkU32(0)),
+                               mkU64(0x000000007fffffffULL),
+                               mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        binop(Iop_And32,
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t2)),
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t3))),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16))),
+                                  getDSPControl()));
+         /* Calculate second cross dot product and saturate if
+            needed. */
+         assign(t5, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl
+            register. */
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t6)),
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t7))),
+                                     mkU32(0)),
+                               mkU64(0x000000007fffffffULL),
+                               mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        binop(Iop_And32,
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t6)),
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t7))),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16))),
+                                  getDSPControl()));
+         /* Subtract intermediate products from value in the
+            accumulator. */
+         assign(t9,
+                binop(Iop_Add64,
+                      mkexpr(t0),
+                      binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
+
+         putAcc(ac,
+                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                 binop(Iop_And32,
+                                       unop(Iop_64HIto32,
+                                            mkexpr(t9)),
+                                       mkU32(0x80000000)),
+                                 mkU32(0x0)),
+                           IRExpr_ITE(binop(Iop_CmpNE32,
+                                            unop(Iop_64HIto32,
+                                                 binop(Iop_Shl64,
+                                                       mkexpr(t9),
+                                                       mkU8(1))),
+                                            mkU32(0x0)),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t9)),
+                           IRExpr_ITE(binop(Iop_CmpNE32,
+                                            unop(Iop_64HIto32,
+                                                 binop(Iop_Shl64,
+                                                       mkexpr(t9),
+                                                       mkU8(1))),
+                                            mkU32(0xffffffff)),
+                                      mkU64(0xffffffff80000000ULL),
+                                      mkexpr(t9))));
+         assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      unop(Iop_64to32,
+                                           mkexpr(t9)),
+                                      unop(Iop_64to32,
+                                           getAcc(ac))),
+                                getDSPControl(),
+                                binop(Iop_Or32,
+                                      getDSPControl(),
+                                      binop(Iop_Shl32,
+                                            mkU32(0x1),
+                                            mkU8(ac + 16)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        unop(Iop_64HIto32,
+                                             mkexpr(t9)),
+                                        unop(Iop_64HIto32,
+                                             getAcc(ac))),
+                                  mkexpr(t10),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         break;
+      }
+
+      case 0x1B: {  /* DPSQX_SA.W.PH */
+         DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
+         vassert(!mode64);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         t2 = newTemp(Ity_I1);
+         t3 = newTemp(Ity_I1);
+         t4 = newTemp(Ity_I64);
+         t5 = newTemp(Ity_I64);
+         t6 = newTemp(Ity_I1);
+         t7 = newTemp(Ity_I1);
+         t8 = newTemp(Ity_I64);
+         t9 = newTemp(Ity_I64);
+         t10 = newTemp(Ity_I32);
+
+         assign(t0, getAcc(ac));
+         /* Calculate the first cross dot product and saturate if
+            needed. */
+         assign(t1, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl
+            register. */
+         assign(t2, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t3, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t2)),
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t3))),
+                                     mkU32(0)),
+                               mkU64(0x000000007fffffffULL),
+                               mkexpr(t1)));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        binop(Iop_And32,
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t2)),
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t3))),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16))),
+                                  getDSPControl()));
+         /* Calculate second cross dot product and saturate if
+            needed. */
+         assign(t5, unop(Iop_32Sto64,
+                         binop(Iop_Shl32,
+                               binop(Iop_Mul32,
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32to16,
+                                               getIReg(rs))),
+                                     unop(Iop_16Sto32,
+                                          unop(Iop_32HIto16,
+                                               getIReg(rt)))),
+                               mkU8(0x1))));
+
+         /* If both input arguments are equal 0x8000, saturate
+            intermediate product and write to DSPControl
+            register. */
+         assign(t6, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32to16, getIReg(rs))),
+                          mkU32(0x00008000)));
+         assign(t7, binop(Iop_CmpEQ32,
+                          unop(Iop_16Uto32,
+                               unop(Iop_32HIto16, getIReg(rt))),
+                          mkU32(0x00008000)));
+
+         assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
+                                     binop(Iop_And32,
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t6)),
+                                           unop(Iop_1Sto32,
+                                                mkexpr(t7))),
+                                     mkU32(0)),
+                               mkU64(0x000000007fffffffULL),
+                               mkexpr(t5)));
+
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
+                                        binop(Iop_And32,
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t6)),
+                                              unop(Iop_1Sto32,
+                                                    mkexpr(t7))),
+                                        mkU32(0)),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16))),
+                                  getDSPControl()));
+         /* Subtract intermediate products from value in the
+            accumulator. */
+         assign(t9,
+                binop(Iop_Sub64,
+                      mkexpr(t0),
+                      binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
+
+         putAcc(ac,
+                IRExpr_ITE(binop(Iop_CmpEQ32,
+                                 binop(Iop_And32,
+                                       unop(Iop_64HIto32,
+                                            mkexpr(t9)),
+                                       mkU32(0x80000000)),
+                                 mkU32(0x0)),
+                           IRExpr_ITE(binop(Iop_CmpNE32,
+                                            unop(Iop_64HIto32,
+                                                 binop(Iop_Shl64,
+                                                       mkexpr(t9),
+                                                       mkU8(1))),
+                                            mkU32(0x0)),
+                                      mkU64(0x000000007fffffffULL),
+                                      mkexpr(t9)),
+                           IRExpr_ITE(binop(Iop_CmpNE32,
+                                            unop(Iop_64HIto32,
+                                                 binop(Iop_Shl64,
+                                                       mkexpr(t9),
+                                                       mkU8(1))),
+                                            mkU32(0xffffffff)),
+                                      mkU64(0xffffffff80000000ULL),
+                                      mkexpr(t9))));
+         assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
+                                      unop(Iop_64to32,
+                                           mkexpr(t9)),
+                                      unop(Iop_64to32,
+                                           getAcc(ac))),
+                                getDSPControl(),
+                                binop(Iop_Or32,
+                                      getDSPControl(),
+                                      binop(Iop_Shl32,
+                                            mkU32(0x1),
+                                            mkU8(ac + 16)))));
+         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
+                                        unop(Iop_64HIto32,
+                                             mkexpr(t9)),
+                                        unop(Iop_64HIto32,
+                                             getAcc(ac))),
+                                  mkexpr(t10),
+                                  binop(Iop_Or32,
+                                        getDSPControl(),
+                                        binop(Iop_Shl32,
+                                              mkU32(0x1),
+                                              mkU8(ac + 16)))));
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3_APPEND( UInt cins )
+{
+   IRTemp t1 = 0, t2, t3;
+   UInt   rs, rt, rd, sa;
+
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+
+   switch (sa) {
+      case 0x0: {  /* APPEND */
+         DIP("append r%u, r%u, %u", rt, rs, rd);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));
+
+         if (31 == rd) {
+            putIReg(rt, binop(Iop_Or32,
+                              mkexpr(t1),
+                              binop(Iop_And32,
+                                    getIReg(rs),
+                                    mkU32(0x7fffffff))));
+         } else if (1 == rd) {
+            putIReg(rt,
+                    binop(Iop_Or32,
+                          mkexpr(t1),
+                          binop(Iop_And32,
+                                getIReg(rs), mkU32(0x1))));
+         } else {
+            assign(t2,
+                   unop(Iop_Not32,
+                        binop(Iop_Shl32,
+                              mkU32(0xffffffff), mkU8(rd))));
+
+            putIReg(rt, binop(Iop_Or32,
+                              mkexpr(t1),
+                              binop(Iop_And32,
+                                    getIReg(rs), mkexpr(t2))));
+         }
+
+         break;
+      }
+
+      case 0x1: {  /* PREPEND */
+         DIP("prepend r%u, r%u, %u", rt, rs, rd);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         if (0 != rd) {
+            assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));
+
+            if (31 == rd) {
+               putIReg(rt, binop(Iop_Or32,
+                                 mkexpr(t1),
+                                 binop(Iop_Shl32,
+                                       binop(Iop_And32,
+                                             getIReg(rs),
+                                             mkU32(0x7fffffff)),
+                                       mkU8(1))));
+            } else if (1 == rd) {
+               putIReg(rt, binop(Iop_Or32,
+                                 mkexpr(t1),
+                                 binop(Iop_Shl32,
+                                       binop(Iop_And32,
+                                             getIReg(rs),
+                                             mkU32(0x1)),
+                                       mkU8(31))));
+            } else {
+               assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));
+
+               assign(t3, unop(Iop_Not32,
+                               binop(Iop_Shl32,
+                                     mkU32(0xffffffff),
+                                     unop(Iop_32to8, mkexpr(t2)))));
+
+               putIReg(rt, binop(Iop_Or32,
+                                 mkexpr(t1),
+                                 binop(Iop_Shl32,
+                                       binop(Iop_And32,
+                                             getIReg(rs),
+                                             mkexpr(t3)),
+                                       mkU8(32 - rd))));
+            }
+         }
+
+         break;
+      }
+
+      case 0x10: {  /* BALIGN */
+         DIP("balign r%u, r%u, %u", rt, rs, rd);
+         vassert(!mode64);
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+
+         if ((2 != rd) && (0 != rd)) {
+            assign(t1, binop(Iop_Shl32,
+                             binop(Iop_And32,
+                                   mkU32(rd), mkU32(0x3)),
+                             mkU8(0x3)));
+            assign(t2, binop(Iop_Shl32,
+                             getIReg(rt),
+                             unop(Iop_32to8, mkexpr(t1))));
+            assign(t3, binop(Iop_Shr32,
+                             getIReg(rs),
+                             unop(Iop_32to8,
+                                  binop(Iop_Shl32,
+                                        binop(Iop_Sub32,
+                                              mkU32(0x4),
+                                              binop(Iop_And32,
+                                                    mkU32(rd),
+                                                    mkU32(0x3))),
+                                        mkU8(0x3)))));
+            putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
+         }
+
+         break;
+      }
+
+      default:
+         return -1;
+   }
+
+   return 0;
+}
+
+static UInt disDSPInstr_MIPS_WRK_Special3( UInt cins )
+{
+   switch (get_function(cins)) {
+      case 0x12: {  /* ABSQ_S.PH */
+         return disDSPInstr_MIPS_WRK_Special3_ABSQ_SPH(cins);
+      }
+
+      case 0x38: {  /* EXTR.W */
+         return disDSPInstr_MIPS_WRK_Special3_EXTR_W(cins);
+      }
+
+      case 0xA: {  /* LX */
+         return disDSPInstr_MIPS_WRK_Special3_LX(cins);
+      }
+
+      case 0xC: {  /* INSV */
+         return disDSPInstr_MIPS_WRK_Special3_INSV(cins);
+      }
+
+      case 0x10: {  /* ADDU.QB */
+         return disDSPInstr_MIPS_WRK_Special3_ADDU_QB(cins);
+      }
+
+      case 0x11: {  /* CMPU.EQ.QB */
+         return disDSPInstr_MIPS_WRK_Special3_CMPU_EQ_QB(cins);
+      }
+
+      case 0x13: {  /* SHLL.QB */
+         return disDSPInstr_MIPS_WRK_Special3_SHLL_QB(cins);
+      }
+
+      case 0x18: {  /* ADDUH.QB/MUL.PH */
+         return disDSPInstr_MIPS_WRK_Special3_ADDUH_QB(cins);
+      }
+
+      case 0x30: {  /* DPA.W.PH */
+         return disDSPInstr_MIPS_WRK_Special3_DPAW_PH(cins);
+      }
+
+      case 0x31: {  /* APPEND */
+         return disDSPInstr_MIPS_WRK_Special3_APPEND(cins);
+      }
+
+      default:
+         return -1;
+   }
+}
+
+UInt disDSPInstr_MIPS_WRK ( UInt cins )
+{
+   UInt opcode = get_opcode(cins);
+
+   switch (opcode) {
+      case 0x00: {  /* Special */
+         return disDSPInstr_MIPS_WRK_Special(cins);
+      }
+
+      case 0x1C: {  /* Special2 */
+         return disDSPInstr_MIPS_WRK_Special2(cins);
+      }
+
+      case 0x1F: {  /* Special3 */
+         return disDSPInstr_MIPS_WRK_Special3(cins);
+      }
+
+      default:
+         return -1;
+   }
+}
diff --git a/VEX/priv/mips_defs.h b/VEX/priv/mips_defs.h
new file mode 100644 (file)
index 0000000..fed46ac
--- /dev/null
@@ -0,0 +1,421 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                                       mips_defs.h ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2017-2019 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+#ifndef __VEX_MIPS_DEFS_H
+#define __VEX_MIPS_DEFS_H
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+
+/* MOD: The IRSB* into which we're generating code. */
+extern IRSB *irsb;
+
+/* Is our guest binary 32 or 64bit? Set at each call to
+   disInstr_MIPS below. */
+extern Bool mode64;
+
+/* Pointer to the guest code area. */
+extern const UChar *guest_code;
+
+/*------------------------------------------------------------*/
+/*---              DSP to IR function                      ---*/
+/*------------------------------------------------------------*/
+
+UInt disDSPInstr_MIPS_WRK ( UInt );
+
+/*------------------------------------------------------------*/
+/*---                  Debugging output                    ---*/
+/*------------------------------------------------------------*/
+
+#define DIP(format, args...)           \
+   if (vex_traceflags & VEX_TRACE_FE)  \
+      vex_printf(format, ## args)
+
+/* ------------ MIPS32 DSP ASE(r2) accumulators ------------- */
+
+extern UInt accumulatorGuestRegOffset( UInt );
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments.    ---*/
+/*------------------------------------------------------------*/
+
+static inline IRExpr *mkU8(UInt i)
+{
+   vassert(i < 256);
+   return IRExpr_Const(IRConst_U8((UChar) i));
+}
+
+/* Create an expression node for a 16-bit integer constant. */
+static inline IRExpr *mkU16(UInt i)
+{
+   return IRExpr_Const(IRConst_U16(i));
+}
+
+/* Create an expression node for a 32-bit integer constant. */
+static inline IRExpr *mkU32(UInt i)
+{
+   return IRExpr_Const(IRConst_U32(i));
+}
+
+/* Create an expression node for a 64-bit integer constant. */
+static inline IRExpr *mkU64(ULong i)
+{
+   return IRExpr_Const(IRConst_U64(i));
+}
+
+static inline IRExpr *mkexpr(IRTemp tmp)
+{
+   return IRExpr_RdTmp(tmp);
+}
+
+static inline IRExpr *unop(IROp op, IRExpr * a)
+{
+   return IRExpr_Unop(op, a);
+}
+
+static inline IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
+{
+   return IRExpr_Binop(op, a1, a2);
+}
+
+static inline IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
+{
+   return IRExpr_Triop(op, a1, a2, a3);
+}
+
+static inline IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
+                     IRExpr * a4 )
+{
+   return IRExpr_Qop(op, a1, a2, a3, a4);
+}
+
+static inline IRExpr *load(IRType ty, IRExpr * addr)
+{
+   IRExpr *load1 = NULL;
+#if defined (_MIPSEL)
+   load1 = IRExpr_Load(Iend_LE, ty, addr);
+#elif defined (_MIPSEB)
+   load1 = IRExpr_Load(Iend_BE, ty, addr);
+#endif
+   return load1;
+}
+
+/* Add a statement to the list held by "irsb". */
+static inline void stmt(IRStmt * st)
+{
+   addStmtToIRSB(irsb, st);
+}
+
+static inline void assign(IRTemp dst, IRExpr * e)
+{
+   stmt(IRStmt_WrTmp(dst, e));
+}
+
+static inline void store(IRExpr * addr, IRExpr * data)
+{
+#if defined (_MIPSEL)
+   stmt(IRStmt_Store(Iend_LE, addr, data));
+#elif defined (_MIPSEB)
+   stmt(IRStmt_Store(Iend_BE, addr, data));
+#endif
+}
+
+/* Generate a new temporary of the given type. */
+static inline IRTemp newTemp(IRType ty)
+{
+   vassert(isPlausibleIRType(ty));
+   return newIRTemp(irsb->tyenv, ty);
+}
+
+static inline UShort extend_s_9to16(UInt x)
+{
+   return (UShort) ((((Int) x) << 23) >> 23);
+}
+
+static inline UShort extend_s_10to16(UInt x)
+{
+   return (UShort) ((((Int) x) << 22) >> 22);
+}
+
+static inline UInt extend_s_10to32(UInt x)
+{
+   return (UInt)((((Int) x) << 22) >> 22);
+}
+
+static inline ULong extend_s_10to64(UInt x)
+{
+   return (ULong)((((Long) x) << 54) >> 54);
+}
+
+static inline UInt extend_s_16to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 16) >> 16);
+}
+
+static inline UInt extend_s_18to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 14) >> 14);
+}
+
+static inline UInt extend_s_19to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 13) >> 13);
+}
+
+static inline UInt extend_s_23to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 9) >> 9);
+}
+
+static inline UInt extend_s_26to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 6) >> 6);
+}
+
+static inline ULong extend_s_16to64 ( UInt x )
+{
+   return (ULong) ((((Long) x) << 48) >> 48);
+}
+
+static inline ULong extend_s_18to64 ( UInt x )
+{
+   return (ULong) ((((Long) x) << 46) >> 46);
+}
+
+static inline ULong extend_s_19to64(UInt x)
+{
+   return (ULong) ((((Long) x) << 45) >> 45);
+}
+
+static inline ULong extend_s_23to64(UInt x)
+{
+   return (ULong) ((((Long) x) << 41) >> 41);
+}
+
+static inline ULong extend_s_26to64(UInt x)
+{
+   return (ULong) ((((Long) x) << 38) >> 38);
+}
+
+static inline ULong extend_s_32to64 ( UInt x )
+{
+   return (ULong) ((((Long) x) << 32) >> 32);
+}
+
+extern IRExpr *getIReg(UInt);
+
+extern void putIReg(UInt, IRExpr *);
+
+/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
+   This function should be called before any other operation if widening
+   multiplications are used. */
+extern IRExpr *getAcc(UInt acNo);
+
+extern IRExpr *getDSPControl(void);
+
+extern IRExpr *mkNarrowTo32(IRType, IRExpr *);
+
+extern void putLO(IRExpr *);
+
+extern void putHI(IRExpr *);
+
+/*------------------------------------------------------------*/
+/*---                  Field helpers                       ---*/
+/*------------------------------------------------------------*/
+
+static inline UInt get_opcode(UInt mipsins)
+{
+   return (0xFC000000 & mipsins) >> 26;
+}
+
+static inline UInt get_rs(UInt mipsins)
+{
+   return (0x03E00000 & mipsins) >> 21;
+}
+
+static inline UInt get_rt(UInt mipsins)
+{
+   return (0x001F0000 & mipsins) >> 16;
+}
+
+static inline UInt get_imm(UInt mipsins)
+{
+   return (0x0000FFFF & mipsins);
+}
+
+static inline UInt get_instr_index(UInt mipsins)
+{
+   return (0x03FFFFFF & mipsins);
+}
+
+static inline UInt get_rd(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static inline UInt get_sa(UInt mipsins)
+{
+   return (0x000007C0 & mipsins) >> 6;
+}
+
+static inline UInt get_function(UInt mipsins)
+{
+   return (0x0000003F & mipsins);
+}
+
+static inline UInt get_ft(UInt mipsins)
+{
+   return (0x001F0000 & mipsins) >> 16;
+}
+
+static inline UInt get_fs(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static inline UInt get_fd(UInt mipsins)
+{
+   return (0x000007C0 & mipsins) >> 6;
+}
+
+static inline UInt get_mov_cc(UInt mipsins)
+{
+   return (0x001C0000 & mipsins) >> 18;
+}
+
+static inline UInt get_bc1_cc(UInt mipsins)
+{
+   return (0x001C0000 & mipsins) >> 18;
+}
+
+static inline UInt get_fpc_cc(UInt mipsins)
+{
+   return (0x00000700 & mipsins) >> 8;
+}
+
+static inline UInt get_tf(UInt mipsins)
+{
+   return (0x00010000 & mipsins) >> 16;
+}
+
+static inline UInt get_nd(UInt mipsins)
+{
+   return (0x00020000 & mipsins) >> 17;
+}
+
+static inline UInt get_fmt(UInt mipsins)
+{
+   return (0x03E00000 & mipsins) >> 21;
+}
+
+static inline UInt get_FC(UInt mipsins)
+{
+   return (0x000000F0 & mipsins) >> 4;
+}
+
+static inline UInt get_cond(UInt mipsins)
+{
+   return (0x0000000F & mipsins);
+}
+
+/* for break & syscall */
+static inline UInt get_code(UInt mipsins)
+{
+   return (0xFFC0 & mipsins) >> 6;
+}
+
+static inline UInt get_lsb(UInt mipsins)
+{
+   return (0x7C0 & mipsins) >> 6;
+}
+
+static inline UInt get_msb(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static inline UInt get_rot(UInt mipsins)
+{
+   return (0x00200000 & mipsins) >> 21;
+}
+
+static inline UInt get_rotv(UInt mipsins)
+{
+   return (0x00000040 & mipsins) >> 6;
+}
+
+static inline UInt get_sel(UInt mipsins)
+{
+   return (0x00000007 & mipsins);
+}
+
+/* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
+   except for MFHI and MFLO. */
+static inline UInt get_acNo(UInt mipsins)
+{
+   return (0x00001800 & mipsins) >> 11;
+}
+
+/* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
+static inline UInt get_acNo_mfhilo(UInt mipsins)
+{
+   return (0x00600000 & mipsins) >> 21;
+}
+
+/* Get mask field (helper function for wrdsp instruction). */
+static inline UInt get_wrdspMask(UInt mipsins)
+{
+   return (0x001ff800 & mipsins) >> 11;
+}
+
+/* Get mask field (helper function for rddsp instruction). */
+static inline UInt get_rddspMask(UInt mipsins)
+{
+   return (0x03ff0000 & mipsins) >> 16;
+}
+
+/* Get shift field (helper function for DSP ASE instructions). */
+static inline UInt get_shift(UInt mipsins)
+{
+   return (0x03f00000 & mipsins) >> 20;
+}
+
+/* Get immediate field for DSP ASE instructions. */
+static inline UInt get_dspImm(UInt mipsins)
+{
+   return (0x03ff0000 & mipsins) >> 16;
+}
+
+
+#endif
+
+/*---------------------------------------------------------------*/
+/*--- end                                         mips_defs.h ---*/
+/*---------------------------------------------------------------*/