]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips32: Fix problem with some mips32 dsp instructions.
authorDejan Jevtic <dejan.jevtic@valgrind.org>
Wed, 23 Oct 2013 14:05:15 +0000 (14:05 +0000)
committerDejan Jevtic <dejan.jevtic@valgrind.org>
Wed, 23 Oct 2013 14:05:15 +0000 (14:05 +0000)
This patch includes VEX optimizations for mips32 and
fixes for some mips32 dsp instructions.

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

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

index 367036d5e41602f9a782af019349f519247c2196..d22adcb09fbb65dc0f8cd9417dc99b47e25df2d3 100644 (file)
@@ -2123,7 +2123,7 @@ static Bool dis_instr_CVM ( UInt theInstr )
    UInt size;
    assign(tmpRs, getIReg(regRs));
 
-   switch(opc2) { 
+   switch(opc2) {
       case 0x03: {  /* DMUL rd, rs, rt */
          DIP("dmul r%d, r%d, r%d", regRd, regRs, regRt);
          IRType t0 = newTemp(Ity_I128);
@@ -2132,7 +2132,7 @@ static Bool dis_instr_CVM ( UInt theInstr )
          break;
       }
       case 0x32:  /* 5. CINS rd, rs, p, lenm1 */
-         DIP("cins r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 
+         DIP("cins r%u, r%u, %d, %d\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));
@@ -2146,7 +2146,7 @@ static Bool dis_instr_CVM ( UInt theInstr )
          break;
 
       case 0x3A:  /* 3. EXTS rt, rs, p len */
-         DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 
+         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 */
@@ -2156,7 +2156,7 @@ static Bool dis_instr_CVM ( UInt theInstr )
          break;
 
       case 0x3B:  /* 4. EXTS32 rt, rs, p len */
-         DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 
+         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));
@@ -2223,7 +2223,7 @@ static Bool dis_instr_CVM ( UInt theInstr )
 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, t18;
+          t15, t16, t17;
    UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
         wrdsp_mask, dsp_imm, shift;
 
@@ -2875,40 +2875,123 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
                      t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I32);
-                     t4 = 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));
-                     assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
-                     putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
+                     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()));
 
-                     assign(t2, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
+                     /* 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)));
 
-                     /* Check if signOut == signIn */
-                     assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t0)),
-                                                       mkU32(0x80000000)),
-                                                 binop(Iop_And32,
-                                                       getIReg(rt),
-                                                       mkU32(0x80000000))),
-                                           getDSPControl(),
-                                           mkexpr(t2)));
+                     /* 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(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 unop(Iop_64HIto32,
-                                                      mkexpr(t1)),
-                                                 mkU32(0x0)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t1)),
-                                                            mkU32(0xffffffff)),
-                                                      mkexpr(t2),
-                                                      mkexpr(t3)),
-                                           mkexpr(t3)));
-                     putDSPControl(mkexpr(t4));
+                     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 */
@@ -2917,43 +3000,133 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
                      t2 = newTemp(Ity_I32);
-                     t3 = 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),
-                                      unop(Iop_32to8,
-                                           binop(Iop_And32,
-                                                 getIReg(rs),
-                                                 mkU32(0x1f)))));
-                     putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
-
-                     assign(t2, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
+                     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 signOut == signIn */
-                     assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t0)),
-                                                       mkU32(0x80000000)),
-                                                 binop(Iop_And32,
-                                                       getIReg(rt),
-                                                       mkU32(0x80000000))),
-                                           getDSPControl(),
-                                           mkexpr(t2)));
+                     /* 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,
-                                      unop(Iop_64HIto32, mkexpr(t1)),
+                                      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,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t1)),
-                                                    mkU32(0x0)),
-                                              IRExpr_ITE(mkexpr(t4),
-                                                         mkexpr(t2),
-                                                         mkexpr(t3)),
-                                              mkexpr(t3)));
+                                                    mkexpr(t14),
+                                                    mkU32(0)),
+                                              binop(Iop_Or32,
+                                                    getDSPControl(),
+                                                    mkU32(0x00800000)),
+                                              getDSPControl()));
                      break;
                   }
                   case 0x2: {  /* EXTP */
@@ -3140,61 +3313,131 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
                      t2 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
+                     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));
-                     if (0 == rs) {
-                        putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
-                     } else {
-                        assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+                     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(t2, binop(Iop_Or32,
-                                         getDSPControl(), mkU32(0x800000)));
+                     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)));
 
-                        putDSPControl(IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            unop(Iop_64HIto32, mkexpr(t1)),
-                                            mkU32(0x0)),
-                                      IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t1)),
-                                                       mkU32(0xffffffff)),
-                                                 mkexpr(t2),
-                                                 getDSPControl()),
-                                      getDSPControl()));
-
-                        assign(t4, binop(Iop_Or32,
-                                         getDSPControl(), mkU32(0x800000)));
-                        /* 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(t5, binop(Iop_Shr64,
-                                         binop(Iop_And64,
-                                               mkexpr(t0),
-                                               binop(Iop_Shl64,
-                                                     mkU64(0x1ULL),
-                                                     mkU8(rs-1))),
-                                         mkU8(rs-1)));
+                     /* 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()));
 
-                        assign(t6, binop(Iop_Add64, mkexpr(t1), mkexpr(t5)));
+                     /* 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)));
 
-                        putDSPControl(IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            unop(Iop_64HIto32, mkexpr(t6)),
-                                                 mkU32(0x0)),
-                                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t6)),
-                                                             mkU32(0xffffffff)),
-                                                       mkexpr(t4),
-                                                       getDSPControl()),
-                                            getDSPControl()));
-                        putIReg(rt, unop(Iop_64to32, mkexpr(t6)));
-                     }
+                     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 */
@@ -3203,79 +3446,129 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
                      t2 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
-
-                     assign(t0, getAcc(ac));
-
-                     assign(t1, binop(Iop_Sar64,
-                                      mkexpr(t0),
-                                      unop(Iop_32to8,
-                                           binop(Iop_And32,
-                                                 getIReg(rs),
-                                                 mkU32(0x1f)))));
+                     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(t2, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
+                     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)));
 
-                     putDSPControl(IRExpr_ITE(
-                                   binop(Iop_CmpNE32,
-                                         unop(Iop_64HIto32, mkexpr(t1)),
-                                         mkU32(0x0)),
-                                   IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t1)),
-                                                    mkU32(0xffffffff)),
-                                              mkexpr(t2),
-                                              getDSPControl()),
-                                   getDSPControl()));
+                     /* 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()));
 
-                     assign(t4, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
                      /* 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(t5, binop(Iop_Shr64,
-                                      binop(Iop_And64,
-                                            mkexpr(t0),
-                                            binop(Iop_Shl64,
-                                                  mkU64(0x1ULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Sub32,
-                                                             binop(Iop_And32,
-                                                                   getIReg(rs),
-                                                                   mkU32(0x1f)),
-                                                             mkU32(0x1))))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 binop(Iop_And32,
-                                                       getIReg(rs),
-                                                       mkU32(0x1f)),
-                                                 mkU32(0x1)))));
+                        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(t6, binop(Iop_Add64, mkexpr(t1), mkexpr(t5)));
+                     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)));
 
-                     putDSPControl(IRExpr_ITE(
-                                   binop(Iop_CmpNE32,
-                                         unop(Iop_64HIto32, mkexpr(t6)),
-                                         mkU32(0x0)),
-                                   IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t6)),
-                                                    mkU32(0xffffffff)),
-                                              mkexpr(t4),
-                                              getDSPControl()),
-                                   getDSPControl()));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x1f)),
-                                                  mkU32(0x0)),
-                                            unop(Iop_64to32, mkexpr(t0)),
-                                            unop(Iop_64to32, mkexpr(t6))));
+                     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 */
@@ -3283,81 +3576,136 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      vassert(!mode64);
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I64);
-                     t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = newTemp(Ity_I32);
+                     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);
 
-                     if (0 != rs) {
-                        assign(t0, getAcc(ac));
+                     assign(t0, getAcc(ac));
+                     if (0 == rs) {
+                        assign(t1, mkexpr(t0));
+                     } else {
                         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
-                        putDSPControl(IRExpr_ITE(
-                                      binop(Iop_CmpNE32,
-                                            unop(Iop_64HIto32, mkexpr(t1)),
-                                            mkU32(0x0)),
-                                      IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t1)),
-                                                       mkU32(0xffffffff)),
-                                                 binop(Iop_Or32,
-                                                       getDSPControl(),
-                                                       mkU32(0x00800000)),
-                                                 getDSPControl()),
-                                      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(t2, binop(Iop_Add64,
-                                         mkexpr(t1),
-                                         binop(Iop_Shr64,
-                                               binop(Iop_And64,
-                                                     mkexpr(t0),
-                                                     binop(Iop_Shl64,
-                                                           mkU64(0x1ULL),
-                                                           unop(Iop_32to8,
-                                                                mkU32(rs-1)))),
-                                               unop(Iop_32to8, mkU32(rs-1)))));
-                        assign(t6, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t2)),
-                                                    mkU32(0xffffffff)),
+                     }
+
+                     /* 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()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t2)),
-                                                       mkU32(0x0)),
-                                                 mkexpr(t6),
-                                                 getDSPControl()));
-                        assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               mkexpr(t2)),
-                                                          mkU32(0x80000000)),
-                                                    mkU32(0x0)),
-                                              mkU32(0x7fffffff),
-                                              mkU32(0x80000000)));
-                        assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t2)),
-                                                    mkU32(0xffffffff)),
-                                              mkexpr(t3),
-                                              unop(Iop_64to32, mkexpr(t2))));
-                        assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t2)),
-                                                    mkU32(0x0)),
-                                              mkexpr(t4),
-                                              unop(Iop_64to32, mkexpr(t2))));
-                        putIReg(rt, mkexpr(t5));
+
+                     /* 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 {
-                        putIReg(rt, unop(Iop_64to32, getAcc(ac)));
+                        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 */
@@ -3366,104 +3714,146 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I64);
                      t1 = newTemp(Ity_I64);
                      t2 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I64);
-                     t6 = newTemp(Ity_I64);
+                     t3 = newTemp(Ity_I1);
+                     t4 = newTemp(Ity_I1);
+                     t5 = newTemp(Ity_I1);
+                     t6 = newTemp(Ity_I1);
                      t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
-                     t9 = newTemp(Ity_I32);
-                     t10 = 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)))));
 
-                     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(t10, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  unop(Iop_64HIto32,
-                                                       mkexpr(t1)),
-                                                  mkU32(0x0)),
-                                            IRExpr_ITE(binop(Iop_CmpNE32,
-                                                             unop(Iop_64HIto32,
-                                                                  mkexpr(t1)),
-                                                             mkU32(0xffffffff)),
-                                                       mkexpr(t2),
-                                                       getDSPControl()),
-                                            getDSPControl()));
-
-                     putDSPControl(mkexpr(t10));
+                     /* 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()));
 
-                     assign(t4, binop(Iop_Or32,
-                                      getDSPControl(), mkU32(0x00800000)));
                      /* 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(t5, binop(Iop_Shr64,
-                                      binop(Iop_And64,
-                                            mkexpr(t0),
-                                            binop(Iop_Shl64,
-                                                  mkU64(0x1ULL),
-                                                  unop(Iop_32to8,
-                                                       binop(Iop_Sub32,
-                                                             binop(Iop_And32,
-                                                                   getIReg(rs),
-                                                                   mkU32(0x1f)),
-                                                             mkU32(0x1))))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_Sub32,
-                                                 binop(Iop_And32,
-                                                       getIReg(rs),
-                                                       mkU32(0x1f)),
-                                                 mkU32(0x1)))));
+                        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(t6, binop(Iop_Add64, mkexpr(t1), mkexpr(t5)));
+                     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(t8, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 unop(Iop_64HIto32,
-                                                      mkexpr(t6)),
-                                                 mkU32(0xffffffff)),
-                                           mkexpr(t4),
-                                           getDSPControl()));
+                     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,
-                                                    unop(Iop_64HIto32,
-                                                         mkexpr(t6)),
-                                                    mkU32(0x0)),
-                                              mkexpr(t8),
+                                                    mkexpr(t14),
+                                                    mkU32(0)),
+                                              binop(Iop_Or32,
+                                                    getDSPControl(),
+                                                    mkU32(0x00800000)),
                                               getDSPControl()));
-                     assign(t9, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t6)),
+
+                     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)),
-                                                 mkU32(0x0)),
-                                           mkU32(0x7fffffff),
-                                           mkU32(0x80000000)));
-                     assign(t7, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                 unop(Iop_64HIto32, mkexpr(t6)),
-                                                 mkU32(0x0)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t6)),
-                                                            mkU32(0xffffffff)),
-                                                      mkexpr(t9),
-                                                      unop(Iop_64to32,
-                                                           mkexpr(t6))),
-                                           unop(Iop_64to32, mkexpr(t6))));
-                     putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                  binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x1f)),
-                                                  mkU32(0x0)),
-                                            unop(Iop_64to32, mkexpr(t0)),
-                                            mkexpr(t7)));
+                                            unop(Iop_64to32, mkexpr(t9))));
                      break;
                   }
                   case 0xA: {  /* EXTPDP */
@@ -3678,9 +4068,7 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t5 = newTemp(Ity_I32);
                      t6 = newTemp(Ity_I64);
                      t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
                      t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I1);
 
                      assign(t0, getAcc(ac));
 
@@ -3689,12 +4077,10 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      assign(t2, binop(Iop_Or32,
                                       getDSPControl(), mkU32(0x00800000)));
 
-                     assign(t9, binop(Iop_Shl32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x00008000)),
-                                      mkU8(16)));
+                     assign(t9, binop(Iop_And32,
+                                      unop(Iop_64to32,
+                                           mkexpr(t1)),
+                                      mkU32(0x80000000)));
                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                                     mkexpr(t9),
                                                     binop(Iop_And32,
@@ -3711,120 +4097,79 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      assign(t3, binop(Iop_Sub64,
                                       mkexpr(t1),
                                       mkU64(0x0000000000007fffULL)));
-                     assign(t4, binop(Iop_Or32,
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t3)),
-                                                       mkU32(0x7fffffff)))),
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
+                     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)),
-                                                       mkU32(0xffffffff))))));
-
-                     assign(t5, IRExpr_ITE(unop(Iop_32to1,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t3)),
-                                                            mkU32(0x80000000)),
-                                                      mkU8(31))),
-                                           unop(Iop_64to32, mkexpr(t1)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            mkexpr(t4),
-                                                            mkU32(0x0)),
-                                                      mkU32(0x7fff),
-                                                      unop(Iop_64to32,
-                                                           mkexpr(t1)))));
-
-                     assign(t10, unop(Iop_32to1,
-                                      binop(Iop_Shr32,
-                                            binop(Iop_And32,
-                                                  unop(Iop_64HIto32,
-                                                       mkexpr(t3)),
-                                                   mkU32(0x80000000)),
-                                            mkU8(31))));
-                     putDSPControl(IRExpr_ITE(mkexpr(t10),
-                                             getDSPControl(),
-                                             IRExpr_ITE(binop(Iop_CmpNE32,
-                                                              mkexpr(t4),
-                                                              mkU32(0x0)),
-                                                        binop(Iop_Or32,
-                                                             getDSPControl(),
-                                                             mkU32(0x00800000)),
-                                                        getDSPControl())));
-
+                                                            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 0x7fff
+                        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_Or32,
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t6)),
-                                                       mkU32(0x7fffffff)))),
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t6)),
-                                                       mkU32(0xffffffff))))));
-
-                     assign(t8, IRExpr_ITE(unop(Iop_32to1,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t6)),
-                                                            mkU32(0x80000000)),
-                                                      mkU8(31))),
-                                           unop(Iop_64to32, mkexpr(t1)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            mkexpr(t7),
-                                                            mkU32(0x0)),
-                                                      mkU32(0xffff8000),
-                                                      unop(Iop_64to32,
-                                                           mkexpr(t1)))));
-                     putDSPControl(IRExpr_ITE(unop(Iop_32to1,
-                                                   binop(Iop_Shr32,
-                                                         binop(Iop_And32,
-                                                             unop(Iop_64HIto32,
-                                                                   mkexpr(t6)),
-                                                             mkU32(0x80000000)),
-                                                         mkU8(31))),
-                                              getDSPControl(),
-                                              IRExpr_ITE(binop(Iop_CmpNE32,
-                                                               mkexpr(t7),
-                                                               mkU32(0x0)),
-                                                         binop(Iop_Or32,
-                                                             getDSPControl(),
-                                                             mkU32(0x00800000)),
-                                                         getDSPControl())));
-
-                     /* If the shifted value is positive, it can only be >0x7fff
-                        and the final result is the value stored in t5,
-                        otherwise, the final result is in t8. */
-                     putIReg(rt, IRExpr_ITE(unop(Iop_32to1,
-                                                 binop(Iop_Shr32,
+                     assign(t7, binop(Iop_And32,
+                                      binop(Iop_Or32,
+                                            unop(Iop_1Sto32,
+                                                 binop(Iop_CmpNE32,
+                                                       mkU32(0),
                                                        binop(Iop_And32,
                                                              unop(Iop_64HIto32,
-                                                                  mkexpr(t1)),
+                                                                  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)),
-                                                       mkU8(31))),
-                                            mkexpr(t8),
-                                            mkexpr(t5)));
+                                                  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 */
@@ -3838,10 +4183,7 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t5 = newTemp(Ity_I32);
                      t6 = newTemp(Ity_I64);
                      t7 = newTemp(Ity_I32);
-                     t8 = newTemp(Ity_I32);
                      t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
 
                      assign(t0, getAcc(ac));
 
@@ -3855,12 +4197,10 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      assign(t2, binop(Iop_Or32,
                                       getDSPControl(), mkU32(0x00800000)));
 
-                     assign(t9, binop(Iop_Shl32,
-                                      binop(Iop_And32,
-                                            unop(Iop_64to32,
-                                                 mkexpr(t1)),
-                                            mkU32(0x00008000)),
-                                      mkU8(16)));
+                     assign(t9, binop(Iop_And32,
+                                      unop(Iop_64to32,
+                                           mkexpr(t1)),
+                                      mkU32(0x80000000)));
                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                                     mkexpr(t9),
                                                     binop(Iop_And32,
@@ -3873,127 +4213,83 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      /* 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 */
+                           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_Or32,
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t3)),
-                                                       mkU32(0x7fffffff)))),
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
+                     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)),
-                                                       mkU32(0xffffffff))))));
-
-                     assign(t5, IRExpr_ITE(unop(Iop_32to1,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t3)),
-                                                            mkU32(0x80000000)),
-                                                      mkU8(31))),
-                                           unop(Iop_64to32, mkexpr(t1)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            mkexpr(t4),
-                                                            mkU32(0x0)),
-                                                      mkU32(0x7fff),
-                                                      unop(Iop_64to32,
-                                                           mkexpr(t1)))));
-
-                     assign(t10, binop(Iop_Shr32,
-                                       binop(Iop_And32,
-                                             unop(Iop_64HIto32,
-                                                  mkexpr(t3)),
-                                             mkU32(0x80000000)),
-                                       mkU8(31)));
-                     assign(t11, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  mkexpr(t4),
-                                                  mkU32(0x0)),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  mkU32(0x00800000)),
-                                            getDSPControl()));
-                     putDSPControl(IRExpr_ITE(unop(Iop_32to1,
-                                                   mkexpr(t10)),
-                                              getDSPControl(),
-                                              mkexpr(t11)));
-
-                     /* Check if t1<0xffffffffffff8000
-                        1. subtract t1 from 0x7fff
-                        2. if the resulting number is positive (sign bit == 0)
+                                                            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_Or32,
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64HIto32,
-                                                            mkexpr(t6)),
-                                                       mkU32(0x7fffffff)))),
-                                      unop(Iop_1Uto32,
-                                           binop(Iop_CmpNE32,
-                                                 mkU32(0),
-                                                 binop(Iop_And32,
-                                                       unop(Iop_64to32,
-                                                            mkexpr(t6)),
-                                                       mkU32(0xffffffff))))));
-
-                     assign(t8, IRExpr_ITE(unop(Iop_32to1,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            unop(Iop_64HIto32,
-                                                                 mkexpr(t6)),
-                                                            mkU32(0x80000000)),
-                                                      mkU8(31))),
-                                           unop(Iop_64to32, mkexpr(t1)),
-                                           IRExpr_ITE(binop(Iop_CmpNE32,
-                                                            mkexpr(t7),
-                                                            mkU32(0x0)),
-                                                      mkU32(0xffff8000),
-                                                      unop(Iop_64to32,
-                                                           mkexpr(t1)))));
-                     putDSPControl(IRExpr_ITE(unop(Iop_32to1,
-                                                  binop(Iop_Shr32,
-                                                        binop(Iop_And32,
-                                                              unop(Iop_64HIto32,
-                                                                   mkexpr(t6)),
-                                                              mkU32(0x80000000)
-                                                             ),
-                                                        mkU8(31))),
-                                              getDSPControl(),
-                                              IRExpr_ITE(binop(Iop_CmpNE32,
-                                                               mkexpr(t7),
-                                                               mkU32(0x0)),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               mkU32(0x00800000)
-                                                              ),
-                                                         getDSPControl())));
-
-                     /* If the shifted value is positive, it can only be >0x7fff
-                        and the final result is the value stored in t5,
-                        otherwise, the final result is in t8. */
-                     putIReg(rt, IRExpr_ITE(unop(Iop_32to1,
-                                                 binop(Iop_Shr32,
+                                       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(t1)),
+                                                                  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)),
-                                                       mkU8(31))),
-                                            mkexpr(t8),
-                                            mkexpr(t5)));
+                                                  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*/
@@ -4192,38 +4488,38 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      DIP("shilov ac%d, r%d", ac, rs);
                      vassert(!mode64);
                      t0 = newTemp(Ity_I64);
-                     t1 = newTemp(Ity_I64);
-                     t2 = newTemp(Ity_I32);
-                     t3 = newTemp(Ity_I1);
+                     t1 = newTemp(Ity_I32);
+                     t2 = newTemp(Ity_I1);
+                     t3 = newTemp(Ity_I64);
                      t4 = newTemp(Ity_I64);
-                     t5 = newTemp(Ity_I64);
 
                      assign(t0, getAcc(ac));
-                     assign(t2, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
-                     assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x20)));
-
-                     assign(t4, binop(Iop_Shl64,
+                     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(t2)),
+                                                      mkexpr(t1)),
                                                  mkU32(0x1)))));
-                     assign(t5, binop(Iop_Shr64,
+                     assign(t4, binop(Iop_Shr64,
                                       mkexpr(t0),
                                       unop(Iop_32to8,
-                                           mkexpr(t2))));
-                     putAcc(ac, IRExpr_ITE(mkexpr(t3),
-                                           binop(Iop_32HLto64,
-                                                 unop(Iop_64to32, mkexpr(t0)),
-                                                 mkU32(0x0)),
-                                           IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                            binop(Iop_And32,
-                                                                  mkexpr(t2),
-                                                                  mkU32(0x20)),
-                                                            mkU32(0x20)),
-                                                      mkexpr(t4),
-                                                      mkexpr(t5))));
+                                           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 */
@@ -7201,160 +7497,113 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I32);
                      t1 = newTemp(Ity_I1);
                      t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = 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_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I32);
-                     t16 = newTemp(Ity_I1);
-                     t17 = newTemp(Ity_I1);
-                     t18 = newTemp(Ity_I32);
+                     t9 = newTemp(Ity_I1);
+                     t10 = newTemp(Ity_I1);
 
                      if (0 == rs) {
                         putIReg(rd, getIReg(rt));
                      } else {
-                        /* Shift bits 7..0. */
+                        /* Shift bits 7..0 and 23..16. */
                         assign(t0, binop(Iop_Shl32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_32to8, getIReg(rt))),
-                                         unop(Iop_32to8,
-                                              binop(Iop_And32,
-                                                    mkU32(rs),
-                                                    mkU32(0x7)))));
-                        /* Check if discard isn't 0x0 and 0xffffffff. */
+                                         binop(Iop_And32,
+                                               getIReg(rt),
+                                               mkU32(0x00ff00ff)),
+                                         mkU8(rs)));
                         assign(t1, binop(Iop_CmpNE32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_16HIto8,
-                                                   unop(Iop_32to16,
-                                                        mkexpr(t0)))),
-                                         mkU32(0x00000000)));
+                                        binop(Iop_And32,
+                                              mkexpr(t0),
+                                              mkU32(0xff000000)),
+                                        mkU32(0x00000000)));
                         assign(t2, binop(Iop_CmpNE32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_16HIto8,
-                                                   unop(Iop_32to16,
-                                                        mkexpr(t0)))),
-                                         mkU32(0x000000ff)));
-                        assign(t4, binop(Iop_Or32,
-                                         getDSPControl(), mkU32(0x400000)));
-                        putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                                 IRExpr_ITE(mkexpr(t2),
-                                                            mkexpr(t4),
-                                                            getDSPControl()),
-                                                 getDSPControl()));
-
-                        /* Shift bits 15..8. */
-                        assign(t5, binop(Iop_Shl32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_16HIto8,
-                                                   unop(Iop_32to16,
-                                                        getIReg(rt)))),
-                                         unop(Iop_32to8,
-                                              binop(Iop_And32,
-                                                    mkU32(rs),
-                                                    mkU32(0x7)))));
-                        /* Check if discard isn't 0x0 and 0xffffffff. */
-                        assign(t6, binop(Iop_CmpNE32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_16HIto8,
-                                                   unop(Iop_32to16,
-                                                        mkexpr(t5)))),
-                                         mkU32(0x00000000)));
+                                        binop(Iop_And32,
+                                              mkexpr(t0),
+                                              mkU32(0xff000000)),
+                                        mkU32(0xff000000)));
                         assign(t7, binop(Iop_CmpNE32,
-                                         unop(Iop_8Uto32,
-                                              unop(Iop_16HIto8,
-                                                   unop(Iop_32to16,
-                                                        mkexpr(t5)))),
-                                         mkU32(0x000000ff)));
-                        assign(t9, binop(Iop_Or32,
-                                         getDSPControl(),
-                                         mkU32(0x400000)));
-                        putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                                 IRExpr_ITE(mkexpr(t7),
-                                                            mkexpr(t9),
-                                                            getDSPControl()),
-                                                 getDSPControl()));
+                                        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)));
 
-                        /* Shift bits 23..16. */
-                        assign(t10, binop(Iop_Shl32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16to8,
-                                                    unop(Iop_32HIto16,
-                                                         getIReg(rt)))),
-                                          unop(Iop_32to8,
+                        assign(t6, binop(Iop_Or32,
+                                         binop(Iop_Or32,
                                                binop(Iop_And32,
-                                                     mkU32(rs),
-                                                     mkU32(0x7)))));
-                        /* Check if discard isn't 0x0 and 0xffffffff. */
-                        assign(t11, binop(Iop_CmpNE32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16HIto8,
-                                                    unop(Iop_32to16,
-                                                         mkexpr(t10)))),
-                                          mkU32(0x00000000)));
-                        assign(t12, binop(Iop_CmpNE32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16HIto8,
-                                                    unop(Iop_32to16,
-                                                         mkexpr(t10)))),
-                                          mkU32(0x000000ff)));
-
-                        assign(t14, binop(Iop_Or32,
-                                          getDSPControl(),
-                                          mkU32(0x400000)));
-                        putDSPControl(IRExpr_ITE(mkexpr(t11),
-                                                 IRExpr_ITE(mkexpr(t12),
-                                                            mkexpr(t14),
-                                                            getDSPControl()),
-                                                 getDSPControl()));
-
-                        /* Shift bits 31..24. */
-                        assign(t15, binop(Iop_Shl32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16HIto8,
-                                                    unop(Iop_32HIto16,
-                                                         getIReg(rt)))),
-                                          unop(Iop_32to8,
+                                                     unop(Iop_1Uto32,
+                                                          mkexpr(t1)),
+                                                     unop(Iop_1Uto32,
+                                                          mkexpr(t2))),
                                                binop(Iop_And32,
-                                                     mkU32(rs),
-                                                     mkU32(0x7)))));
-                        /* Check if discard isn't 0x0 and 0xffffffff. */
-                        assign(t16, binop(Iop_CmpNE32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16HIto8,
-                                                    unop(Iop_32to16,
-                                                         mkexpr(t15)))),
-                                          mkU32(0x00000000)));
-                        assign(t17, binop(Iop_CmpNE32,
-                                          unop(Iop_8Uto32,
-                                               unop(Iop_16HIto8,
-                                                    unop(Iop_32to16,
-                                                         mkexpr(t15)))),
-                                          mkU32(0x000000ff)));
-
-                        assign(t18, binop(Iop_Or32,
-                                          getDSPControl(),
-                                          mkU32(0x400000)));
-                        putDSPControl(IRExpr_ITE(mkexpr(t16),
-                                                 IRExpr_ITE(mkexpr(t17),
-                                                            mkexpr(t18),
-                                                            getDSPControl()),
-                                                 getDSPControl()));
+                                                     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))))));
 
-                        putIReg(rd, binop(Iop_16HLto32,
-                                          binop(Iop_8HLto16,
-                                                unop(Iop_32to8, mkexpr(t15)),
-                                                unop(Iop_32to8, mkexpr(t10))),
-                                          binop(Iop_8HLto16,
-                                                unop(Iop_32to8, mkexpr(t5)),
-                                                unop(Iop_32to8, mkexpr(t0)))));
+                        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;
                   }
@@ -7422,165 +7671,119 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t0 = newTemp(Ity_I32);
                      t1 = newTemp(Ity_I1);
                      t2 = newTemp(Ity_I1);
-                     t3 = newTemp(Ity_I1);
-                     t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I32);
-                     t6 = 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_I32);
-                     t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I1);
-                     t12 = newTemp(Ity_I1);
-                     t13 = newTemp(Ity_I1);
-                     t14 = newTemp(Ity_I32);
-                     t15 = newTemp(Ity_I32);
-                     t16 = newTemp(Ity_I1);
-                     t17 = newTemp(Ity_I1);
-                     t18 = newTemp(Ity_I32);
+                     t9 = newTemp(Ity_I1);
+                     t10 = newTemp(Ity_I1);
+                     t11 = newTemp(Ity_I8);
 
-                     /* Shift bits 7..0. */
+                     assign(t11, unop(Iop_32to8,
+                                      binop(Iop_And32,
+                                            getIReg(rs),
+                                            mkU32(0x7))));
+                     /* Shift bits 7..0 and 23..16. */
                      assign(t0, binop(Iop_Shl32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_32to8, getIReg(rt))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_And32,
-                                                 getIReg(rs),
-                                                 mkU32(0x7)))));
-                     /* Check if discard isn't 0x0 and 0xffffffff. */
+                                      binop(Iop_And32,
+                                            getIReg(rt),
+                                            mkU32(0x00ff00ff)),
+                                      mkexpr(t11)));
                      assign(t1, binop(Iop_CmpNE32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, mkexpr(t0)))),
-                                      mkU32(0x00000000)));
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0xff000000)),
+                                     mkU32(0x00000000)));
                      assign(t2, binop(Iop_CmpNE32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, mkexpr(t0)))),
-                                      mkU32(0x000000ff)));
-
-                     assign(t4, binop(Iop_Or32,
-                                      getDSPControl(),
-                                      mkU32(0x400000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t1),
-                                              IRExpr_ITE(mkexpr(t2),
-                                                         mkexpr(t4),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     /* Shift bits 15..8. */
-                     assign(t5, binop(Iop_Shl32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, getIReg(rt)))),
-                                      unop(Iop_32to8,
-                                           binop(Iop_And32,
-                                                 getIReg(rs),
-                                                 mkU32(0x7)))));
-                     /* Check if discard isn't 0x0 and 0xffffffff. */
-                     assign(t6, binop(Iop_CmpNE32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, mkexpr(t5)))),
-                                       mkU32(0x00000000)));
+                                     binop(Iop_And32,
+                                           mkexpr(t0),
+                                           mkU32(0xff000000)),
+                                     mkU32(0xff000000)));
                      assign(t7, binop(Iop_CmpNE32,
-                                      unop(Iop_8Uto32,
-                                           unop(Iop_16HIto8,
-                                                unop(Iop_32to16, mkexpr(t5)))),
-                                      mkU32(0x000000ff)));
-
-                     assign(t9, binop(Iop_Or32,
-                                      getDSPControl(),
-                                      mkU32(0x400000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         mkexpr(t9),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     /* Shift bits 23..16. */
-                     assign(t10, binop(Iop_Shl32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16to8,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                       unop(Iop_32to8,
+                                     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(rs),
-                                                  mkU32(0x7)))));
-                     /* Check if discard isn't 0x0 and 0xffffffff. */
-                     assign(t11, binop(Iop_CmpNE32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32to16,
-                                                      mkexpr(t10)))),
-                                       mkU32(0x00000000)));
-                     assign(t12, binop(Iop_CmpNE32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32to16,
-                                                      mkexpr(t10)))),
-                                       mkU32(0x000000ff)));
-
-                     assign(t14, binop(Iop_Or32,
-                                       getDSPControl(),
-                                       mkU32(0x400000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t11),
-                                              IRExpr_ITE(mkexpr(t12),
-                                                         mkexpr(t14),
-                                                         getDSPControl()),
-                                              getDSPControl()));
-
-                     /* Shift bits 31..24. */
-                     assign(t15, binop(Iop_Shl32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32HIto16,
-                                                      getIReg(rt)))),
-                                       unop(Iop_32to8,
+                                                  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,
-                                                  getIReg(rs),
-                                                  mkU32(0x7)))));
-                     /* Check if discard isn't 0x0 and 0xffffffff. */
-                     assign(t16, binop(Iop_CmpNE32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32to16,
-                                                      mkexpr(t15)))),
-                                       mkU32(0x00000000)));
-                     assign(t17, binop(Iop_CmpNE32,
-                                       unop(Iop_8Uto32,
-                                            unop(Iop_16HIto8,
-                                                 unop(Iop_32to16,
-                                                      mkexpr(t15)))),
-                                       mkU32(0x000000ff)));
-
-                     assign(t18, binop(Iop_Or32,
-                                       getDSPControl(),
-                                       mkU32(0x400000)));
-                     putDSPControl(IRExpr_ITE(mkexpr(t16),
-                                              IRExpr_ITE(mkexpr(t17),
-                                                         mkexpr(t18),
-                                                         getDSPControl()),
-                                              getDSPControl()));
+                                                  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,
-                                                  binop(Iop_And32,
-                                                        getIReg(rs),
-                                                        mkU32(0x7)),
-                                                  mkU32(0x0)),
+                                                  unop(Iop_8Uto32, mkexpr(t11)),
+                                                  mkU32(0)),
                                             getIReg(rt),
-                                            binop(Iop_16HLto32,
-                                                  binop(Iop_8HLto16,
-                                                        unop(Iop_32to8,
-                                                             mkexpr(t15)),
-                                                        unop(Iop_32to8,
-                                                             mkexpr(t10))),
-                                                  binop(Iop_8HLto16,
-                                                        unop(Iop_32to8,
-                                                             mkexpr(t5)),
-                                                        unop(Iop_32to8,
-                                                             mkexpr(t0))))));
+                                            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 */
@@ -8075,7 +8278,10 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t1 = newTemp(Ity_I32);
                      t2 = newTemp(Ity_I32);
                      t3 = newTemp(Ity_I32);
-                     t4 = newTemp(Ity_I1);
+                     t4 = newTemp(Ity_I32);
+                     t5 = newTemp(Ity_I32);
+                     t6 = newTemp(Ity_I32);
+                     t7 = newTemp(Ity_I32);
 
                      if (0 == rs) {
                         putIReg(rd, getIReg(rt));
@@ -8086,21 +8292,27 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                               unop(Iop_32to16, getIReg(rt))),
                                          mkU8(rs)));
 
-                        assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_16Sto32,
-                                                         unop(Iop_32HIto16,
-                                                              mkexpr(t0))),
-                                                    mkU32(0xffffffff)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_16Sto32,
-                                                            unop(Iop_32HIto16,
-                                                                 mkexpr(t0))),
-                                                       mkU32(0x00000000)),
-                                                 mkexpr(t2),
+                        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,
@@ -8115,46 +8327,56 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                                        getDSPControl(),
                                                        mkU32(0x400000))));
                         /* Shift higher 16 bits. */
-                        assign(t1, binop(Iop_Shl32,
+                        assign(t4, binop(Iop_Shl32,
                                          unop(Iop_16Sto32,
                                               unop(Iop_32HIto16, getIReg(rt))),
                                          mkU8(rs)));
 
-                        assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_16Sto32,
-                                                         unop(Iop_32HIto16,
-                                                              mkexpr(t1))),
-                                                    mkU32(0xffffffff)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                     unop(Iop_16Sto32,
-                                                          unop(Iop_32HIto16,
-                                                               mkexpr(t1))),
-                                                     mkU32(0x00000000)),
-                                                mkexpr(t3),
-                                                getDSPControl()));
-                        assign(t4, binop(Iop_CmpEQ32,
-                                         binop(Iop_Shr32,
-                                               binop(Iop_And32,
-                                                     getIReg(rt),
-                                                     mkU32(0x80000000)),
-                                               mkU8(31)),
-                                         binop(Iop_Shr32,
-                                               binop(Iop_And32,
-                                                     mkexpr(t1),
-                                                     mkU32(0x00008000)),
-                                               mkU8(15))));
-                        putDSPControl(IRExpr_ITE(mkexpr(t4),
+                        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(t1)),
+                                          unop(Iop_32to16, mkexpr(t4)),
                                           unop(Iop_32to16, mkexpr(t0))));
                      }
                      break;
@@ -8323,18 +8545,20 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      DIP("shll_s.ph r%d, r%d, %d", rd, rt, rs);
                      vassert(!mode64);
                      t0 = newTemp(Ity_I32);
-                     t1 = newTemp(Ity_I16);
-                     t2 = newTemp(Ity_I16);
-                     t3 = newTemp(Ity_I16);
+                     t1 = newTemp(Ity_I32);
+                     t2 = newTemp(Ity_I32);
+                     t3 = newTemp(Ity_I32);
                      t4 = newTemp(Ity_I32);
-                     t5 = newTemp(Ity_I16);
-                     t6 = newTemp(Ity_I16);
-                     t7 = newTemp(Ity_I16);
+                     t5 = newTemp(Ity_I32);
+                     t6 = newTemp(Ity_I32);
+                     t7 = newTemp(Ity_I32);
                      t8 = newTemp(Ity_I32);
                      t9 = newTemp(Ity_I32);
-                     t10 = newTemp(Ity_I1);
-                     t11 = newTemp(Ity_I16);
-                     t12 = newTemp(Ity_I16);
+                     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));
@@ -8345,146 +8569,158 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                               unop(Iop_32to16, getIReg(rt))),
                                          mkU8(rs)));
 
-                        assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_And32,
-                                                          getIReg(rt),
-                                                          mkU32(0x00008000)),
-                                                    mkU32(0x0)),
-                                              mkU16(0x7fff),
-                                              mkU16(0x8000)));
-                        assign(t2,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            getIReg(rt),
-                                                            mkU32(0x00008000)),
-                                                      mkU8(15)),
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            mkexpr(t0),
-                                                            mkU32(0x00008000)),
-                                                      mkU8(15))),
-                                          unop(Iop_32to16, mkexpr(t0)),
-                                          mkexpr(t1)));
-                        assign(t11, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                     unop(Iop_16Sto32,
-                                                          unop(Iop_32HIto16,
-                                                               mkexpr(t0))),
-                                                     mkU32(0xffffffff)),
-                                               mkexpr(t1),
-                                               mkexpr(t2)));
-                        assign(t3,
-                               IRExpr_ITE(binop(Iop_CmpNE32,
-                                                unop(Iop_16Sto32,
-                                                     unop(Iop_32HIto16,
-                                                          mkexpr(t0))),
-                                                mkU32(0x00000000)),
-                                          mkexpr(t11),
-                                          mkexpr(t2)));
-                        assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_16Sto32,
-                                                         unop(Iop_32HIto16,
-                                                              mkexpr(t0))),
-                                                    mkU32(0xffffffff)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_16Sto32,
-                                                            unop(Iop_32HIto16,
-                                                                 mkexpr(t0))),
-                                                       mkU32(0x00000000)),
-                                                mkexpr(t8),
-                                                getDSPControl()));
+                        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))),
+                                                             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, IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                    binop(Iop_And32,
-                                                          getIReg(rt),
-                                                          mkU32(0x80000000)),
-                                                    mkU32(0x0)),
-                                              mkU16(0x7fff),
-                                              mkU16(0x8000)));
-                        assign(t6,
-                               IRExpr_ITE(binop(Iop_CmpEQ32,
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            getIReg(rt),
-                                                            mkU32(0x80000000)),
-                                                      mkU8(31)),
-                                                binop(Iop_Shr32,
-                                                      binop(Iop_And32,
-                                                            mkexpr(t4),
-                                                            mkU32(0x00008000)),
-                                                      mkU8(15))),
-                                          unop(Iop_32to16, mkexpr(t4)),
-                                          mkexpr(t5)));
-                        assign(t12, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                     unop(Iop_16Sto32,
-                                                          unop(Iop_32HIto16,
-                                                               mkexpr(t4))),
-                                                     mkU32(0xffffffff)),
-                                               mkexpr(t5),
-                                               mkexpr(t6)));
-                        assign(t7,
-                               IRExpr_ITE(binop(Iop_CmpNE32,
-                                                unop(Iop_16Sto32,
-                                                     unop(Iop_32HIto16,
-                                                          mkexpr(t4))),
-                                                mkU32(0x00000000)),
-                                          mkexpr(t12),
-                                          mkexpr(t6)));
-                        assign(t9, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                    unop(Iop_16Sto32,
-                                                      unop(Iop_32HIto16,
-                                                           mkexpr(t4))),
-                                                    mkU32(0xffffffff)),
-                                              binop(Iop_Or32,
-                                                    getDSPControl(),
-                                                    mkU32(0x400000)),
-                                              getDSPControl()));
-                        putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
-                                                       unop(Iop_16Sto32,
-                                                            unop(Iop_32HIto16,
-                                                                 mkexpr(t4))),
-                                                       mkU32(0x00000000)),
-                                                 mkexpr(t9),
+                        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()));
-                        assign(t10, binop(Iop_CmpEQ32,
-                                          binop(Iop_Shr32,
-                                                binop(Iop_And32,
-                                                      getIReg(rt),
-                                                      mkU32(0x80000000)),
-                                                mkU8(31)),
-                                          binop(Iop_Shr32,
-                                                binop(Iop_And32,
-                                                      mkexpr(t4),
-                                                      mkU32(0x00008000)),
-                                                mkU8(15))));
-                        putDSPControl(IRExpr_ITE(mkexpr(t10),
+                        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))));
-
-                        putIReg(rd, binop(Iop_16HLto32,
-                                          mkexpr(t7), mkexpr(t3)));
+                        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;
                   }
@@ -10831,10 +11067,9 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t8 = newTemp(Ity_I64);
                      t9 = newTemp(Ity_I64);
                      t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
 
                      assign(t0, getAcc(ac));
-                     /* Calculate first cross dot product and saturate if
+                     /* Calculate the first cross dot product and saturate if
                         needed. */
                      assign(t1, unop(Iop_32Sto64,
                                      binop(Iop_Shl32,
@@ -10859,23 +11094,28 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                            unop(Iop_32to16, getIReg(rt))),
                                       mkU32(0x00008000)));
 
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
+                     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(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
+                     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. */
@@ -10902,29 +11142,35 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                            unop(Iop_32HIto16, getIReg(rt))),
                                       mkU32(0x00008000)));
 
-                     assign(t8,
-                            IRExpr_ITE(mkexpr(t6),
-                                       IRExpr_ITE(mkexpr(t7),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t5)),
-                                       mkexpr(t5)));
+                     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(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
+                     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()));
-                     /* Add intermediate products with value in the
+                     /* Subtract intermediate products from value in the
                         accumulator. */
-                     assign(t9, binop(Iop_Add64,
-                                     mkexpr(t0),
-                                     binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
+                     assign(t9,
+                            binop(Iop_Add64,
+                                  mkexpr(t0),
+                                  binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
 
                      putAcc(ac,
                             IRExpr_ITE(binop(Iop_CmpEQ32,
@@ -10949,38 +11195,28 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                                         mkU32(0xffffffff)),
                                                   mkU64(0xffffffff80000000ULL),
                                                   mkexpr(t9))));
-                     assign(t10, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  unop(Iop_64HIto32,
-                                                       binop(Iop_Shl64,
-                                                             mkexpr(t9),
-                                                             mkU8(1))),
-                                                  mkU32(0x0)),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  binop(Iop_Shl32,
-                                                        mkU32(0x1),
-                                                        mkU8(ac+16))),
-                                            getDSPControl()));
-                     assign(t11, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  unop(Iop_64HIto32,
-                                                       binop(Iop_Shl64,
-                                                             mkexpr(t9),
-                                                             mkU8(1))),
-                                                  mkU32(0xffffffff)),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  binop(Iop_Shl32,
-                                                        mkU32(0x1),
-                                                        mkU8(ac+16))),
-                                            getDSPControl()));
+                     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,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               mkexpr(t9)),
-                                                          mkU32(0x80000000)),
-                                                    mkU32(0x0)),
+                                                    unop(Iop_64HIto32,
+                                                         mkexpr(t9)),
+                                                    unop(Iop_64HIto32,
+                                                         getAcc(ac))),
                                               mkexpr(t10),
-                                              mkexpr(t11)));
+                                              binop(Iop_Or32,
+                                                    getDSPControl(),
+                                                    binop(Iop_Shl32,
+                                                          mkU32(0x1),
+                                                          mkU8(ac+16)))));
                      break;
                   }
                   case 0x1B: {  /* DPSQX_SA.W.PH */
@@ -10997,10 +11233,9 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                      t8 = newTemp(Ity_I64);
                      t9 = newTemp(Ity_I64);
                      t10 = newTemp(Ity_I32);
-                     t11 = newTemp(Ity_I32);
 
                      assign(t0, getAcc(ac));
-                     /* Calculate first cross dot product and saturate if
+                     /* Calculate the first cross dot product and saturate if
                         needed. */
                      assign(t1, unop(Iop_32Sto64,
                                      binop(Iop_Shl32,
@@ -11025,23 +11260,28 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                            unop(Iop_32to16, getIReg(rt))),
                                       mkU32(0x00008000)));
 
-                     assign(t4,
-                            IRExpr_ITE(mkexpr(t2),
-                                       IRExpr_ITE(mkexpr(t3),
-                                                  mkU64(0x000000007fffffffULL),
-                                                  mkexpr(t1)),
-                                       mkexpr(t1)));
+                     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(mkexpr(t2),
-                                              IRExpr_ITE(mkexpr(t3),
-                                                         binop(Iop_Or32,
-                                                               getDSPControl(),
-                                                               binop(Iop_Shl32,
-                                                                     mkU32(0x1),
-                                                                     mkU8(ac+16)
-                                                                    )
-                                                              ),
-                                                         getDSPControl()),
+                     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. */
@@ -11060,31 +11300,36 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                         intermediate product and write to DSPControl
                         register. */
                      assign(t6, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rs),
-                                            mkU32(0x0000ffff)),
+                                      unop(Iop_16Uto32,
+                                           unop(Iop_32to16, getIReg(rs))),
                                       mkU32(0x00008000)));
                      assign(t7, binop(Iop_CmpEQ32,
-                                      binop(Iop_And32,
-                                            getIReg(rt),
-                                            mkU32(0xffff0000)),
-                                      mkU32(0x80000000)));
+                                      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)));
+                     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(mkexpr(t6),
-                                              IRExpr_ITE(mkexpr(t7),
-                                                         binop(Iop_Or32,
-                                                         getDSPControl(),
-                                                         binop(Iop_Shl32,
-                                                               mkU32(0x1),
-                                                               mkU8(ac+16))),
-                                                         getDSPControl()),
+                     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. */
@@ -11116,38 +11361,28 @@ static UInt disDSPInstr_MIPS_WRK ( UInt cins )
                                                         mkU32(0xffffffff)),
                                                   mkU64(0xffffffff80000000ULL),
                                                   mkexpr(t9))));
-                     assign(t10, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  unop(Iop_64HIto32,
-                                                       binop(Iop_Shl64,
-                                                             mkexpr(t9),
-                                                             mkU8(1))),
-                                                  mkU32(0x0)),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  binop(Iop_Shl32,
-                                                        mkU32(0x1),
-                                                        mkU8(ac+16))),
-                                            getDSPControl()));
-                     assign(t11, IRExpr_ITE(binop(Iop_CmpNE32,
-                                                  unop(Iop_64HIto32,
-                                                       binop(Iop_Shl64,
-                                                             mkexpr(t9),
-                                                             mkU8(1))),
-                                                  mkU32(0xffffffff)),
-                                            binop(Iop_Or32,
-                                                  getDSPControl(),
-                                                  binop(Iop_Shl32,
-                                                        mkU32(0x1),
-                                                        mkU8(ac+16))),
-                                            getDSPControl()));
+                     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,
-                                                    binop(Iop_And32,
-                                                          unop(Iop_64HIto32,
-                                                               mkexpr(t9)),
-                                                          mkU32(0x80000000)),
-                                                    mkU32(0x0)),
+                                                    unop(Iop_64HIto32,
+                                                         mkexpr(t9)),
+                                                    unop(Iop_64HIto32,
+                                                         getAcc(ac))),
                                               mkexpr(t10),
-                                              mkexpr(t11)));
+                                              binop(Iop_Or32,
+                                                    getDSPControl(),
+                                                    binop(Iop_Shl32,
+                                                          mkU32(0x1),
+                                                          mkU8(ac+16)))));
                      break;
                   }
                   default:
index 1127e677c272a6c5c1ea2cc0b02af6dd7586aa99..1addd045a46e88e1ca5a2675ae64cdfc6ed01d98 100644 (file)
@@ -2101,7 +2101,7 @@ void getRegUsage_MIPSInstr(HRegUsage * u, MIPSInstr * i, Bool mode64)
          addHRegUse(u, HRmRead, i->Min.FpGpMove.src);
          return;
       case Min_MoveCond:
-         addHRegUse(u, HRmWrite, i->Min.MoveCond.dst);
+         addHRegUse(u, HRmModify, i->Min.MoveCond.dst);
          addHRegUse(u, HRmRead, i->Min.MoveCond.src);
          addHRegUse(u, HRmRead, i->Min.MoveCond.cond);
          return;
index 266e27574cd8b7a65f84be9d18026cfec7f6f624..d0017c8726eaba3344a7daee1688f1164560648d 100644 (file)
@@ -235,7 +235,8 @@ static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
 
-/* In 64-bit mode ONLY */
+/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an immediate in
+   the range 1 .. 63 inclusive.  Used for doing shift amounts. */
 static MIPSRH *iselWordExpr_RH6u_wrk(ISelEnv * env, IRExpr * e);
 static MIPSRH *iselWordExpr_RH6u(ISelEnv * env, IRExpr * e);
 
@@ -1789,34 +1790,14 @@ static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
       if ((ty == Ity_I8 || ty == Ity_I16 ||
            ty == Ity_I32 || ((ty == Ity_I64))) &&
            typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
+         HReg r_dst  = iselWordExpr_R(env, e->Iex.ITE.iffalse);
+         HReg r1     = iselWordExpr_R(env, e->Iex.ITE.iftrue);
+         HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
          /*
-          * r_dst = cond && r1
-          * cond = not(cond)
-          * tmp = cond && r0
-          * r_dst = tmp + r_dst
+          * r_dst = r0
+          * movn r_dst, r1, r_cond
           */
-         HReg r0 = iselWordExpr_R(env, e->Iex.ITE.iffalse);
-         HReg r1 = iselWordExpr_R(env, e->Iex.ITE.iftrue);
-         HReg r_cond_1 = iselWordExpr_R(env, e->Iex.ITE.cond);
-         HReg r_cond = newVRegI(env);
-         HReg mask = newVRegI(env);
-         HReg r_dst = newVRegI(env);
-         HReg r_tmp = newVRegI(env);
-         HReg r_tmp1 = newVRegI(env);
-         HReg r_cond_neg = newVRegI(env);
-         /* r_cond = 0 - r_cond_1 */
-         addInstr(env, MIPSInstr_LI(mask, 0x0));
-         addInstr(env, MIPSInstr_Alu(Malu_SUB, r_cond,
-                                     mask, MIPSRH_Reg(r_cond_1)));
-
-         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp, r_cond, MIPSRH_Reg(r1)));
-         addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
-                       MIPSRH_Reg(r_cond)));
-         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1, r_cond_neg,
-                       MIPSRH_Reg(r0)));
-         addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst, r_tmp,
-                       MIPSRH_Reg(r_tmp1)));
-
+         addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, r1, r_cond));
          return r_dst;
       }
       break;
@@ -2009,7 +1990,6 @@ static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
 static MIPSRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
 {
    MIPSRH *ri;
-   vassert(env->mode64);
    ri = iselWordExpr_RH6u_wrk(env, e);
    /* sanity checks ... */
    switch (ri->tag) {
@@ -2436,7 +2416,8 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
             /* Check if borrow is nedded. */
             addInstr(env, MIPSInstr_Cmp(False, size32, borrow, xLo, yLo, cc));
 
-            addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi, MIPSRH_Reg(borrow)));
+            addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi,
+                                        MIPSRH_Reg(borrow)));
             addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, xHi, MIPSRH_Reg(yHi)));
 
             *rHi = tHi;
@@ -2505,177 +2486,271 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
          }
 
          case Iop_Shr64: {
-            HReg xLo, xHi;
-            HReg tLo = newVRegI(env);
-            HReg tLo1 = newVRegI(env);
-            HReg tHi = newVRegI(env);
-            HReg tmp = newVRegI(env);
-            HReg tmp2 = newVRegI(env);
-            HReg tmp3 = newVRegI(env);
-            HReg mask = newVRegI(env);
-            HReg tMask = newVRegI(env);
-            HReg discard = newVRegI(env);
-            HReg discard1 = newVRegI(env);
+#if defined (_MIPSEL)
+            /* 64-bit logical shift right based on what gcc generates:
+               <shift>:
+               nor  v0, zero, a2
+               sll  a3, a1, 0x1
+               sllv a3, a3, v0
+               srlv v0, a0, a2
+               srlv v1, a1, a2
+               andi a0, a2, 0x20
+               or   v0, a3, v0
+               movn v0, v1, a0
+               jr   ra
+               movn v1, zero, a0
+            */
+            HReg a0, a1;
+            HReg a0tmp = newVRegI(env);
+            HReg a2 = newVRegI(env);
+            HReg a3 = newVRegI(env);
+            HReg v0 = newVRegI(env);
+            HReg v1 = newVRegI(env);
+            HReg zero = newVRegI(env);
+            MIPSRH *sa = NULL;
 
-            /* We assume any literal values are on the second operand. */
-            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-            MIPSRH *ri_srcR = NULL;
-            MIPSRH *ri_srcR_sub = NULL;
-
-            ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
-            ri_srcR_sub = iselWordExpr_RH(env, True /*signed */ ,
-                                          e->Iex.Binop.arg2);
-
-            /* Steps:
-               1. Take shift-amount (arg2) least significant bits from upper
-                  half of 64bit input value (arg1)
-               2. Shift upper half
-               3. Shift lower half
-               4. Put discarded bits (those from step 1) to most significant
-                  bit positions of lower half */
-
-            /* Mask for extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_LI(tmp, 0xffffffff));
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         tMask, tmp, ri_srcR));
-            addInstr(env, MIPSInstr_Alu(Malu_NOR, mask,
-                                        tMask, MIPSRH_Reg(tMask)));
-
-            /* Extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_Alu(Malu_AND, discard, xHi,
-                                        MIPSRH_Reg(mask)));
-            /* Position discarded bits to most significant bit positions. */
-            addInstr(env, MIPSInstr_LI(tmp3, 32));
-            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2,
-                                        tmp3, ri_srcR_sub));
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         discard1, discard, MIPSRH_Reg(tmp2)));
-
-            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
-                                         tHi, xHi, ri_srcR));
-            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
-                                         tLo1, xLo, ri_srcR));
-
-            addInstr(env, MIPSInstr_Alu(Malu_OR, tLo,
-                                        tLo1, MIPSRH_Reg(discard1)));
-            *rHi = tHi;
-            *rLo = tLo;
+            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
+            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
+
+            if (sa->tag == Mrh_Imm) {
+               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
+            }
+            else {
+               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
+                                           MIPSRH_Imm(False, 0x3f)));
+            }
+
+            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
+            /* nor  v0, zero, a2 */
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
+            /* sll  a3, a1, 0x1 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a1, MIPSRH_Imm(False, 0x1)));
+            /* sllv a3, a3, v0 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a3, MIPSRH_Reg(v0)));
+            /* srlv v0, a0, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         v0, a0, MIPSRH_Reg(a2)));
+            /* srlv v1, a1, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         v1, a1, MIPSRH_Reg(a2)));
+            /* andi a0, a2, 0x20 */
+            addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
+                                        MIPSRH_Imm(False, 0x20)));
+            /* or   v0, a3, v0 */
+            addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
+
+            /* movn    v0, v1, a0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
+            /* movn    v1, zero, a0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, zero, a0tmp));
+
+            *rHi = v1;
+            *rLo = v0;
             return;
+#elif defined (_MIPSEB)
+            /* 64-bit logical shift right based on what gcc generates:
+               <shift>:
+               nor  v0, zero, a2
+               sll  a3, a0, 0x1
+               sllv a3, a3, v0
+               srlv v1, a1, a2
+               andi v0, a2, 0x20
+               or   v1, a3, v1
+               srlv a2, a0, a2
+               movn v1, a2, v0
+               movn a2, zero, v0
+               jr   ra
+               move v0, a2
+            */
+            HReg a0, a1;
+            HReg a2 = newVRegI(env);
+            HReg a2tmp = newVRegI(env);
+            HReg a3 = newVRegI(env);
+            HReg v0 = newVRegI(env);
+            HReg v1 = newVRegI(env);
+            HReg zero = newVRegI(env);
+            MIPSRH *sa = NULL;
+
+            iselInt64Expr(&a0, &a1, env, e->Iex.Binop.arg1);
+            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
+
+            if (sa->tag == Mrh_Imm) {
+               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
+            }
+            else {
+               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
+                                           MIPSRH_Imm(False, 0x3f)));
+            }
+
+            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
+            /* nor v0, zero, a2 */
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
+            /* sll a3, a0, 0x1 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a0, MIPSRH_Imm(False, 0x1)));
+            /* sllv a3, a3, v0 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a3, MIPSRH_Reg(v0)));
+            /* srlv v1, a1, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         v1, a1, MIPSRH_Reg(a2)));
+            /* andi v0, a2, 0x20 */
+            addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
+                                        MIPSRH_Imm(False, 0x20)));
+            /* or v1, a3, v1 */
+            addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
+            /* srlv a2, a0, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                             a2tmp, a0, MIPSRH_Reg(a2)));
+
+            /* movn v1, a2, v0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2tmp, v0));
+            /* movn  a2, zero, v0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2tmp, zero, v0));
+            /* move v0, a2 */
+            addInstr(env, mk_iMOVds_RR(v0, a2tmp));
+
+            *rHi = v0;
+            *rLo = v1;
+            return;
+#endif
          }
+
          case Iop_Shl64: {
-            HReg xLo, xHi;
-            HReg tLo = newVRegI(env);
-            HReg tHi1 = newVRegI(env);
-            HReg tHi = newVRegI(env);
-            HReg tmp = newVRegI(env);
-            HReg tmp2 = newVRegI(env);
-            HReg tmp3 = newVRegI(env);
-            HReg mask = newVRegI(env);
-            HReg tMask = newVRegI(env);
-            HReg discard = newVRegI(env);
-            HReg discard1 = newVRegI(env);
+            /* 64-bit shift left based on what gcc generates:
+               <shift>:
+               nor  v0,zero,a2
+               srl  a3,a0,0x1
+               srlv a3,a3,v0
+               sllv v1,a1,a2
+               andi v0,a2,0x20
+               or   v1,a3,v1
+               sllv a2,a0,a2
+               movn v1,a2,v0
+               movn a2,zero,v0
+               jr   ra
+               move v0,a2
+            */
+            HReg a0, a1;
+            HReg a2 = newVRegI(env);
+            HReg a3 = newVRegI(env);
+            HReg v0 = newVRegI(env);
+            HReg v1 = newVRegI(env);
+            HReg zero = newVRegI(env);
+            MIPSRH *sa = NULL;
 
-            /* We assume any literal values are on the second operand. */
-            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-            MIPSRH *ri_srcR = NULL;
-            MIPSRH *ri_srcR_sub = NULL;
-
-            ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
-            ri_srcR_sub = iselWordExpr_RH(env, True /*signed */ ,
-                                          e->Iex.Binop.arg2);
-
-            /* Steps:
-               1. Take shift-amount (arg2) most significant bits from lower
-                  half of 64bit input value (arg1)
-               2. Shift lower half
-               3. Shift upper half
-               4. Put discarded bits (those from step 1) to least significant
-                  bit positions of upper half */
-
-            /* Mask for extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_LI(tmp, 0xffffffff));
-            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
-                                         tMask, tmp, ri_srcR));
-            addInstr(env, MIPSInstr_Alu(Malu_NOR, mask,
-                                        tMask, MIPSRH_Reg(tMask)));
-
-            /* Extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_Alu(Malu_AND, discard, xLo,
-                                        MIPSRH_Reg(mask)));
-            /* Position discarded bits to least significant bit positions. */
-            addInstr(env, MIPSInstr_LI(tmp3, 32));
-            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2,
-                                        tmp3, ri_srcR_sub));
-            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
-                                         discard1, discard, MIPSRH_Reg(tmp2)));
-
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         tHi1, xHi, ri_srcR));
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         tLo, xLo, ri_srcR));
-
-            addInstr(env, MIPSInstr_Alu(Malu_OR, tHi,
-                                        tHi1, MIPSRH_Reg(discard1)));
-            *rHi = tHi;
-            *rLo = tLo;
+            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
+            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
+
+            if (sa->tag == Mrh_Imm) {
+               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
+            }
+            else {
+               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
+                                           MIPSRH_Imm(False, 0x3f)));
+            }
+
+            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
+            /* nor v0, zero, a2 */
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
+            /* srl a3, a0, 0x1 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         a3, a0, MIPSRH_Imm(False, 0x1)));
+            /* srlv a3, a3, v0 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         a3, a3, MIPSRH_Reg(v0)));
+            /* sllv v1, a1, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         v1, a1, MIPSRH_Reg(a2)));
+            /* andi v0, a2, 0x20 */
+            addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
+                                        MIPSRH_Imm(False, 0x20)));
+            /* or v1, a3, v1 */
+            addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
+            /* sllv a2, a0, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a2, a0, MIPSRH_Reg(a2)));
+
+            /* movn v1, a2, v0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2, v0));
+            /* movn a2, zero, v0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2, zero, v0));
+            addInstr(env, mk_iMOVds_RR(v0, a2));
+
+            *rHi = v1;
+            *rLo = v0;
             return;
          }
+
          case Iop_Sar64: {
-            HReg xLo, xHi;
-            HReg tLo = newVRegI(env);
-            HReg tLo1 = newVRegI(env);
-            HReg tHi = newVRegI(env);
-            HReg tmp = newVRegI(env);
-            HReg tmp2 = newVRegI(env);
-            HReg tmp3 = newVRegI(env);
-            HReg mask = newVRegI(env);
-            HReg tMask = newVRegI(env);
-            HReg discard = newVRegI(env);
-            HReg discard1 = newVRegI(env);
+            /* 64-bit arithmetic shift right based on what gcc generates:
+               <shift>:
+               nor  v0, zero, a2
+               sll  a3, a1, 0x1
+               sllv a3, a3, v0
+               srlv v0, a0, a2
+               srav v1, a1, a2
+               andi a0, a2, 0x20
+               sra  a1, a1, 0x1f
+               or   v0, a3, v0
+               movn v0, v1, a0
+               jr   ra
+               movn v1, a1, a0
+            */
+            HReg a0, a1;
+            HReg a0tmp = newVRegI(env);
+            HReg a1tmp = newVRegI(env);
+            HReg a2 = newVRegI(env);
+            HReg a3 = newVRegI(env);
+            HReg v0 = newVRegI(env);
+            HReg v1 = newVRegI(env);
+            HReg zero = newVRegI(env);
+            MIPSRH *sa = NULL;
 
-            /* We assume any literal values are on the second operand. */
-            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-            MIPSRH *ri_srcR = NULL;
-            MIPSRH *ri_srcR_sub = NULL;
-
-            ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
-            ri_srcR_sub = iselWordExpr_RH(env, True /*signed */ ,
-                                          e->Iex.Binop.arg2);
-
-            /* Steps:
-               1. Take shift-amount (arg2) least significant bits from upper
-                  half of 64bit input value (arg1)
-               2. Shift upper half
-               3. Shift lower half
-               4. Put discarded bits (those from step 1) to most significant
-                  bit positions of lower half */
-
-            /* Mask for extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_LI(tmp, 0xffffffff));
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         tMask, tmp, ri_srcR));
-            addInstr(env, MIPSInstr_Alu(Malu_NOR, mask,
-                                        tMask, MIPSRH_Reg(tMask)));
-
-            /* Extraction of bits that will be discarded. */
-            addInstr(env, MIPSInstr_Alu(Malu_AND, discard, xHi,
-                                        MIPSRH_Reg(mask)));
-            /* Position discarded bits to most significant bit positions. */
-            addInstr(env, MIPSInstr_LI(tmp3, 32));
-            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2,
-                                        tmp3, ri_srcR_sub));
-            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*32bit shift */,
-                                         discard1, discard, MIPSRH_Reg(tmp2)));
-
-            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /*32bit shift */,
-                                         tHi, xHi, ri_srcR));
-            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
-                                         tLo1, xLo, ri_srcR));
-
-            addInstr(env, MIPSInstr_Alu(Malu_OR, tLo,
-                                        tLo1, MIPSRH_Reg(discard1)));
-            *rHi = tHi;
-            *rLo = tLo;
+            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
+            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
+
+            if (sa->tag == Mrh_Imm) {
+               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
+            }
+            else {
+               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
+                                           MIPSRH_Imm(False, 0x3f)));
+            }
+
+            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
+            /* nor  v0, zero, a2 */
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
+            /* sll  a3, a1, 0x1 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a1, MIPSRH_Imm(False, 0x1)));
+            /* sllv a3, a3, v0 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
+                                         a3, a3, MIPSRH_Reg(v0)));
+            /* srlv v0, a0, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
+                                         v0, a0, MIPSRH_Reg(a2)));
+            /* srav v1, a1, a2 */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
+                                         v1, a1, MIPSRH_Reg(a2)));
+            /* andi a0, a2, 0x20 */
+            addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
+                                        MIPSRH_Imm(False, 0x20)));
+            /* sra a1, a1, 0x1f */
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
+                                         a1tmp, a1, MIPSRH_Imm(False, 0x1f)));
+            /* or   v0, a3, v0 */
+            addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
+
+            /* movn    v0, v1, a0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
+            /* movn    v1, a1, a0 */
+            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a1tmp, a0tmp));
+
+            *rHi = v1;
+            *rLo = v0;
             return;
          }
 
@@ -2695,7 +2770,7 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
 
             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
                           MIPSRH_Imm(False, 31)));
-            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, src,
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
                           MIPSRH_Imm(False, 31)));
 
             addInstr(env, mk_iMOVds_RR(tHi, tmp));
@@ -2748,35 +2823,31 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
          }
 
          case Iop_Left64: {
-            HReg yLo, yHi, borrow;
+            HReg yHi, yLo;
             HReg tHi  = newVRegI(env);
             HReg tLo  = newVRegI(env);
+            HReg tmp  = newVRegI(env);
+            HReg tmp1  = newVRegI(env);
+            HReg tmp2  = newVRegI(env);
             HReg zero = newVRegI(env);
-            Bool size32 = True;
             MIPSCondCode cc = MIPScc_LO;
 
-            borrow = newVRegI(env);
-
             /* yHi:yLo = arg */
             iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
             /* zero = 0 */
             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
 
-            /* tLo = 0 - yLo */
-            addInstr(env, MIPSInstr_Alu(Malu_SUB, tLo, zero, MIPSRH_Reg(yLo)));
-
-            /* Check if borrow is needed. */
-            addInstr(env, MIPSInstr_Cmp(False, size32, borrow, zero, yLo, cc));
+            /* tmp2:tmp1 = 0 - (yHi:yLo)*/
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, zero, MIPSRH_Reg(yLo)));
+            addInstr(env, MIPSInstr_Cmp(False, True, tmp1, zero, tmp2, cc));
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, zero, MIPSRH_Reg(yHi)));
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp1, tmp, MIPSRH_Reg(tmp1)));
 
-            /* tHi = 0 - (yHi + borrow) */
-            addInstr(env, MIPSInstr_Alu(Malu_ADD,
-                                        yHi, yHi, MIPSRH_Reg(borrow)));
-            addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, zero, MIPSRH_Reg(yHi)));
-            /* So now we have tHi:tLo = -arg.  To finish off, or 'arg'
+            /* So now we have tmp2:tmp1 = -arg.  To finish off, or 'arg'
                back in, so as to give the final result
                tHi:tLo = arg | -arg. */
-            addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, tHi, MIPSRH_Reg(yHi)));
-            addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, tLo, MIPSRH_Reg(yLo)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, yHi, MIPSRH_Reg(tmp1)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, yLo, MIPSRH_Reg(tmp2)));
             *rHi = tHi;
             *rLo = tLo;
             return;