#include "libvex_basictypes.h"
#include "libvex_ir.h"
#include "libvex.h"
#include "libvex_guest_mips32.h"
#include "libvex_guest_mips64.h"

#include "main_util.h"
#include "main_globals.h"
#include "guest_generic_bb_to_IR.h"
#include "guest_mips_defs.h"
#include "mips_defs.h"


/* Put value to DSPControl register. Expression e is written to DSPControl as
   is. If only certain bits of DSPControl need to be changed, it should be done
   before calling putDSPControl(). It could be done by reading DSPControl and
   ORing it with appropriate mask. */
static void putDSPControl(IRExpr * e)
{
   vassert(!mode64);
   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
}

/* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
static void putAcc(UInt acNo, IRExpr * e)
{
   vassert(!mode64);
   vassert(acNo <= 3);
   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
   stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));

   /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
      between MIPS32 and MIPS DSP ASE insn sets. */
   if (0 == acNo) {
      putLO(unop(Iop_64to32, e));
      putHI(unop(Iop_64HIto32, e));
   }
}
/*------------------------------------------------------------*/
/*---       Disassemble a single DSP ASE instruction       ---*/
/*------------------------------------------------------------*/

static UInt disDSPInstr_MIPS_WRK_Special ( UInt cins )
{
   IRTemp t1;
   UInt rs, rt, rd, function, ac, ac_mfhilo;
   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   function = get_function(cins);
   ac = get_acNo(cins);
   ac_mfhilo = get_acNo_mfhilo(cins);

   switch (function) {
      case 0x10: {  /* MFHI */
         DIP("mfhi ac%u r%u", ac_mfhilo, rd);
         putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
         break;
      }

      case 0x11: {  /* MTHI */
         DIP("mthi ac%u r%u", ac, rs);
         t1 = newTemp(Ity_I32);
         assign(t1, unop(Iop_64to32, getAcc(ac)));
         putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
         break;
      }

      case 0x12: {  /* MFLO */
         DIP("mflo ac%u r%u", ac_mfhilo, rd);
         putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
         break;
      }

      case 0x13: {  /* MTLO */
         DIP("mtlo ac%u r%u", ac, rs);
         t1 = newTemp(Ity_I32);
         assign(t1, unop(Iop_64HIto32, getAcc(ac)));
         putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
         break;
      }

      case 0x18: {  /* MULT */
         DIP("mult ac%u r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
                          mkNarrowTo32(Ity_I32, getIReg(rt))));
         putAcc(ac, mkexpr(t1));
         break;
      }

      case 0x19: {  /* MULTU */
         DIP("multu ac%u r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
                          mkNarrowTo32(Ity_I32,
                                       getIReg(rt))));
         putAcc(ac, mkexpr(t1));
         break;
      }
   }

   return 0;
}


static UInt disDSPInstr_MIPS_WRK_Special2 ( UInt cins )
{
   IRTemp t1 = 0, t2, t3;
   UInt rs, rt, function, ac;
   rs = get_rs(cins);
   rt = get_rt(cins);
   function = get_function(cins);
   ac = get_acNo(cins);

   switch (function) {
      case 0x00: {  /* MADD */
         DIP("madd ac%u, r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t1, getAcc(ac));
         assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
         assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));

         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0x01: {  /* MADDU */
         DIP("maddu ac%u r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t1, getAcc(ac));
         assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
         assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));

         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0x04: {  /* MSUB */
         DIP("msub ac%u r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t1, getAcc(ac));
         assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
         assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));

         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0x05: {  /* MSUBU */
         DIP("msubu ac%u r%u, r%u", ac, rs, rt);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t1, getAcc(ac));
         assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
         assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));

         putAcc(ac, mkexpr(t3));
         break;
      }
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_ABSQ_SPH( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
              t15, t16, t17;
   UInt   rt, rd, sa, dsp_imm;

   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);
   dsp_imm = get_dspImm(cins);

   switch (sa) {
      case 0x1: {  /* ABSQ_S.QB */
         DIP("absq_s.qb r%u, r%u", rd, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I8);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I8);
         t8 = newTemp(Ity_I8);
         t9 = newTemp(Ity_I1);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I8);
         t12 = newTemp(Ity_I8);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I1);
         t15 = newTemp(Ity_I8);
         t16 = newTemp(Ity_I32);
         t17 = newTemp(Ity_I32);

         /* Absolute value of the rightmost byte (bits 7-0). */
         /* t0 - rightmost byte. */
         assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
         /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
         assign(t1, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32, mkexpr(t0)),
                          mkU32(0x00000080)));
         /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
         assign(t2, unop(Iop_32to1,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     getIReg(rt),
                                     mkU32(0x00000080)),
                               mkU8(0x7))));
         /* t3 holds abs(t0). */
         assign(t3, IRExpr_ITE(mkexpr(t1),
                               mkU8(0x7F),
                               IRExpr_ITE(mkexpr(t2),
                                          binop(Iop_Add8,
                                                unop(Iop_Not8,
                                                      mkexpr(t0)),
                                                mkU8(0x1)),
                                          mkexpr(t0))));

         /* Absolute value of bits 15-8. */
         /* t4 - input byte. */
         assign(t4,
                unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
         /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
         assign(t5, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32, mkexpr(t4)),
                          mkU32(0x00000080)));
         /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
         assign(t6, unop(Iop_32to1,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     getIReg(rt),
                                     mkU32(0x00008000)),
                               mkU8(15))));
         /* t3 holds abs(t4). */
         assign(t7, IRExpr_ITE(mkexpr(t5),
                               mkU8(0x7F),
                               IRExpr_ITE(mkexpr(t6),
                                          binop(Iop_Add8,
                                                unop(Iop_Not8,
                                                      mkexpr(t4)),
                                                mkU8(0x1)),
                                          mkexpr(t4))));

         /* Absolute value of bits 23-15. */
         /* t8 - input byte. */
         assign(t8,
                unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
         /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
         assign(t9, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32, mkexpr(t8)),
                          mkU32(0x00000080)));
         /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
         assign(t10, unop(Iop_32to1,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0x00800000)),
                                mkU8(23))));
         /* t3 holds abs(t8). */
         assign(t11, IRExpr_ITE(mkexpr(t9),
                                mkU8(0x7F),
                                IRExpr_ITE(mkexpr(t10),
                                           binop(Iop_Add8,
                                                 unop(Iop_Not8,
                                                       mkexpr(t8)),
                                                 mkU8(0x1)),
                                           mkexpr(t8))));

         /* Absolute value of bits 31-24. */
         /* t12 - input byte. */
         assign(t12,
                unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
         /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
         assign(t13, binop(Iop_CmpEQ32,
                           unop(Iop_8Uto32, mkexpr(t12)),
                           mkU32(0x00000080)));
         /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
         assign(t14, unop(Iop_32to1,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0x80000000)),
                                mkU8(31))));
         /* t15 holds abs(t12). */
         assign(t15, IRExpr_ITE(mkexpr(t13),
                                mkU8(0x7F),
                                IRExpr_ITE(mkexpr(t14),
                                           binop(Iop_Add8,
                                                 unop(Iop_Not8,
                                                       mkexpr(t12)),
                                                 mkU8(0x1)),
                                           mkexpr(t12))));

         /* t16 holds !0 if any of input bytes is 0x80 or 0
            otherwise. */
         assign(t16,
                binop(Iop_Or32,
                      binop(Iop_Or32,
                            binop(Iop_Or32,
                                  unop(Iop_1Sto32, mkexpr(t13)),
                                  unop(Iop_1Sto32, mkexpr(t9))),
                            unop(Iop_1Sto32, mkexpr(t5))),
                      unop(Iop_1Sto32, mkexpr(t1))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t16),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000))));

         /* t17 = t15|t11|t7|t3 */
         assign(t17,
                binop(Iop_16HLto32,
                      binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
                      binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));

         putIReg(rd, mkexpr(t17));
         break;
      }

      case 0x2: {  /* REPL.QB */
         DIP("repl.qb r%u, %u", rd, dsp_imm);
         vassert(!mode64);

         putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
                           (dsp_imm << 8) | (dsp_imm)));
         break;
      }

      case 0x3: {  /* REPLV.QB */
         DIP("replv.qb r%u, r%u", rd, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I8);

         assign(t0, unop(Iop_32to8,
                         binop(Iop_And32, getIReg(rt), mkU32(0xff))));
         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
                       binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
         break;
      }

      case 0x4: {  /* PRECEQU.PH.QBL */
         DIP("precequ.ph.qbl r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0xff000000)),
                                 mkU8(1)),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x00ff0000)),
                                 mkU8(9))));
         break;
      }

      case 0x5: {  /* PRECEQU.PH.QBR */
         DIP("precequ.ph.qbr r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shl32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x0000ff00)),
                                 mkU8(15)),
                           binop(Iop_Shl32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x000000ff)),
                                 mkU8(7))));
         break;
      }

      case 0x6: {  /* PRECEQU.PH.QBLA */
         DIP("precequ.ph.qbla r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0xff000000)),
                                 mkU8(1)),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x0000ff00)),
                                 mkU8(1))));
         break;
      }

      case 0x7: {  /* PRECEQU.PH.QBRA */
         DIP("precequ.ph.qbra r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shl32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x00ff0000)),
                                 mkU8(7)),
                           binop(Iop_Shl32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x000000ff)),
                                 mkU8(7))));
         break;
      }

      case 0x9: {  /* ABSQ_S.PH */
         DIP("absq_s.ph r%u, r%u", rd, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I16);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I16);
         t4 = newTemp(Ity_I16);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I16);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);

         /* t0 holds lower 16 bits of value in rt. */
         assign(t0, unop(Iop_32to16, getIReg(rt)));
         /* t1 holds 1 if t0 is equal to 0x8000. */
         assign(t1, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32, mkexpr(t0)),
                          mkU32(0x00008000)));
         /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
         assign(t2, unop(Iop_32to1,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     getIReg(rt),
                                     mkU32(0x00008000)),
                               mkU8(15))));
         /* t3 holds abs(t0). */
         assign(t3, IRExpr_ITE(mkexpr(t1),
                               mkU16(0x7FFF),
                               IRExpr_ITE(mkexpr(t2),
                                          binop(Iop_Add16,
                                                unop(Iop_Not16,
                                                      mkexpr(t0)),
                                                mkU16(0x1)),
                                          mkexpr(t0))));

         /* t4 holds lower 16 bits of value in rt. */
         assign(t4, unop(Iop_32HIto16, getIReg(rt)));
         /* t5 holds 1 if t4 is equal to 0x8000. */
         assign(t5, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32, mkexpr(t4)),
                          mkU32(0x00008000)));
         /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
         assign(t6, unop(Iop_32to1,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     getIReg(rt),
                                     mkU32(0x80000000)),
                               mkU8(31))));
         /* t7 holds abs(t4). */
         assign(t7, IRExpr_ITE(mkexpr(t5),
                               mkU16(0x7FFF),
                               IRExpr_ITE(mkexpr(t6),
                                          binop(Iop_Add16,
                                                unop(Iop_Not16,
                                                      mkexpr(t4)),
                                                mkU16(0x1)),
                                          mkexpr(t4))));
         /* If any of the two input halfwords is equal 0x8000,
            set bit 20 in DSPControl register. */
         assign(t8, binop(Iop_Or32,
                          unop(Iop_1Sto32, mkexpr(t5)),
                          unop(Iop_1Sto32, mkexpr(t1))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t8),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000))));

         /* t9 = t7|t3 */
         assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));

         putIReg(rd, mkexpr(t9));
         break;
      }

      case 0xA: {  /* REPL.PH */
         DIP("repl.ph r%u, %u", rd, dsp_imm);
         vassert(!mode64);
         UShort immediate = extend_s_10to16(dsp_imm);

         putIReg(rd, mkU32(immediate << 16 | immediate));
         break;
      }

      case 0xB: {  /* REPLV.PH */
         DIP("replv.ph r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, getIReg(rt)),
                           unop(Iop_32to16, getIReg(rt))));
         break;
      }

      case 0xC: {  /* PRECEQ.W.PHL */
         DIP("preceq.w.phl r%u, r%u", rd, rt);
         vassert(!mode64);
         putIReg(rd, binop(Iop_And32,
                           getIReg(rt),
                           mkU32(0xffff0000)));
         break;
      }

      case 0xD: {  /* PRECEQ.W.PHR */
         DIP("preceq.w.phr r%u, r%u", rd, rt);
         vassert(!mode64);
         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, getIReg(rt)),
                           mkU16(0x0)));
         break;
      }

      case 0x11: {  /* ABSQ_S.W */
         DIP("absq_s.w r%u, r%u", rd, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I1);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);

         assign(t0,
                binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));

         putDSPControl(IRExpr_ITE(mkexpr(t0),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));

         assign(t2, IRExpr_ITE(mkexpr(t0),
                               mkU32(0x7FFFFFFF),
                               IRExpr_ITE(mkexpr(t1),
                                          binop(Iop_Add32,
                                                unop(Iop_Not32,
                                                      getIReg(rt)),
                                                mkU32(0x1)),
                                          getIReg(rt))));
         putIReg(rd, mkexpr(t2));
         break;
      }

      case 0x1B: {  /* BITREV */
         DIP("bitrev r%u, r%u", rd, rt);
         vassert(!mode64);
         /* 32bit reversal as seen on Bit Twiddling Hacks site
            http://graphics.stanford.edu/~seander/bithacks.html
            section ReverseParallel */
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);

         assign(t1, binop(Iop_Or32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0xaaaaaaaa)),
                                mkU8(0x1)),
                          binop(Iop_Shl32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0x55555555)),
                                mkU8(0x1))));
         assign(t2, binop(Iop_Or32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t1),
                                      mkU32(0xcccccccc)),
                                mkU8(0x2)),
                          binop(Iop_Shl32,
                                binop(Iop_And32,
                                      mkexpr(t1),
                                      mkU32(0x33333333)),
                                mkU8(0x2))));
         assign(t3, binop(Iop_Or32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0xf0f0f0f0)),
                                mkU8(0x4)),
                          binop(Iop_Shl32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0x0f0f0f0f)),
                                mkU8(0x4))));
         assign(t4, binop(Iop_Or32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t3),
                                      mkU32(0xff00ff00)),
                                mkU8(0x8)),
                          binop(Iop_Shl32,
                                binop(Iop_And32,
                                      mkexpr(t3),
                                      mkU32(0x00ff00ff)),
                                mkU8(0x8))));
         assign(t5, binop(Iop_Or32,
                          binop(Iop_Shr32,
                                mkexpr(t4),
                                mkU8(0x10)),
                          binop(Iop_Shl32,
                                mkexpr(t4),
                                mkU8(0x10))));
         putIReg(rd, binop(Iop_Shr32,
                           mkexpr(t5),
                           mkU8(16)));
         break;
      }

      case 0x1C: {  /* PRECEU.PH.QBL */
         DIP("preceu.ph.qbl r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0xff000000)),
                                 mkU8(8)),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x00ff0000)),
                                 mkU8(16))));
         break;
      }

      case 0x1E: {  /* PRECEU.PH.QBLA */
         DIP("preceu.ph.qbla r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0xff000000)),
                                 mkU8(8)),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x0000ff00)),
                                 mkU8(8))));
         break;
      }

      case 0x1D: {  /* PRECEU.PH.QBR */
         DIP("preceu.ph.qbr r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Shl32,
                                 binop(Iop_And32,
                                       getIReg(rt),
                                       mkU32(0x0000ff00)),
                                 mkU8(8)),
                           binop(Iop_And32,
                                 getIReg(rt),
                                 mkU32(0x000000ff))));
         break;
      }

      case 0x1F: {  /* PRECEU.PH.QBRA */
         DIP("preceu.ph.qbra r%u, r%u", rd, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_And32,
                                 getIReg(rt),
                                 mkU32(0x00ff0000)),
                           binop(Iop_And32,
                                 getIReg(rt),
                                 mkU32(0x000000ff))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_EXTR_W( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
              t15, t16, t17;
   UInt   rs, rt, rd, sa, ac, rddsp_mask,
          wrdsp_mask, shift;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);
   ac = get_acNo(cins);
   rddsp_mask = get_rddspMask(cins);
   wrdsp_mask = get_wrdspMask(cins);
   shift = get_shift(cins);

   switch (sa) {
      case 0x0: {  /* EXTR.W */
         DIP("extr.w r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));

         if (0 == rs) {
            assign(t1, mkexpr(t0));
         } else {
            assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
         }

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));
         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least sifgnificant bit of the shifted value
            from acc. */
         if (0 == rs) {
            assign(t8, mkU64(0x0ULL));
         } else {
            assign(t8, binop(Iop_And64,
                             binop(Iop_Shr64,
                                   mkexpr(t0),
                                   mkU8(rs - 1)),
                             mkU64(0x1ULL)));
         }

         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         if (0 == rs) {
            putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
         } else {
            putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
         }

         break;
      }

      case 0x1: {  /* EXTRV.W */
         DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);
         t15 = newTemp(Ity_I8);

         assign(t15, unop(Iop_32to8,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0x1f))));
         assign(t0, getAcc(ac));
         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
         putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      unop(Iop_8Uto32,
                                           mkexpr(t15)),
                                      mkU32(0)),
                                unop(Iop_64to32, mkexpr(t0)),
                                unop(Iop_64to32, mkexpr(t1))));

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));
         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least sifgnificant bit of the shifted value
            from acc. */
         assign(t8,
                IRExpr_ITE(binop(Iop_CmpEQ32,
                                 unop(Iop_8Uto32,
                                      mkexpr(t15)),
                                 mkU32(0)),
                           mkU64(0x0ULL),
                           binop(Iop_And64,
                                 binop(Iop_Shr64,
                                       mkexpr(t0),
                                       unop(Iop_32to8,
                                            binop(Iop_Sub32,
                                                  unop(Iop_8Uto32,
                                                        mkexpr(t15)),
                                                  mkU32(1)))),
                                 mkU64(0x1ULL))));

         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         break;
      }

      case 0x2: {  /* EXTP */
         DIP("extp r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));
         /* Extract pos field of DSPControl register. */
         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));

         /* Check if (pos - size) >= 0 [size <= pos]
            if (pos < size)
               put 1 to EFI field of DSPControl register
            else
               extract bits from acc and put 0 to EFI field of
               DSPCtrl */
         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffbfff)),
                                        mkU32(0x4000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xffffbfff))));

         /* If pos <= 31, shift right the value from the acc
            (pos-size) times and take (size+1) bits from the least
            significant positions. Otherwise, shift left the value
            (63-pos) times, take (size+1) bits from the most
            significant positions and shift right (31-size) times.*/
         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));

         assign(t4,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkexpr(t1), mkU32(rs))),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkU32(63), mkexpr(t1)))));

         assign(t5, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Shr64,
                                     mkexpr(t0), mkexpr(t4)),
                               binop(Iop_Shl64,
                                     mkexpr(t0), mkexpr(t4))));

         /* t6 holds a mask for bit extraction */
         assign(t6,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_Not64,
                                binop(Iop_Shl64,
                                      mkU64(0xffffffffffffffffULL),
                                      mkU8(rs + 1))),
                           unop(Iop_Not64,
                                binop(Iop_Shr64,
                                      mkU64(0xffffffffffffffffULL),
                                      mkU8(rs + 1)))));

         assign(t7, IRExpr_ITE(mkexpr(t3),
                               unop(Iop_64to32,
                                    binop(Iop_And64,
                                          mkexpr(t5),
                                          mkexpr(t6))),
                               binop(Iop_Shr32,
                                     unop(Iop_64HIto32,
                                          binop(Iop_And64,
                                                mkexpr(t5),
                                                mkexpr(t6))),
                                     mkU8(31 - rs))));

         putIReg(rt, mkexpr(t7));
         break;
      }

      case 0x3: {  /* EXTPV */
         DIP("extpv r%u, ac%u, r%u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
         assign(t0, getAcc(ac));
         /* Extract pos field of DSPControl register. */
         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));

         /* Check if (pos - size) >= 0 [size <= pos]
            if (pos < size)
               put 1 to EFI field of DSPControl register
            else
               extract bits from acc and put 0 to EFI field of
               DSPCtrl */
         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffbfff)),
                                        mkU32(0x4000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xffffbfff))));

         /* If pos <= 31, shift right the value from the acc
            (pos-size) times and take (size+1) bits from the least
            significant positions. Otherwise, shift left the value
            (63-pos) times, take (size+1) bits from the most
            significant positions and shift right (31-size)
            times. */
         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));

         assign(t4,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkexpr(t1), mkexpr(t8))),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkU32(63), mkexpr(t1)))));

         assign(t5, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Shr64,
                                     mkexpr(t0), mkexpr(t4)),
                               binop(Iop_Shl64,
                                     mkexpr(t0), mkexpr(t4))));

         /* t6 holds a mask for bit extraction. */
         assign(t6,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_Not64,
                                binop(Iop_Shl64,
                                      mkU64(0xffffffffffffffffULL),
                                      unop(Iop_32to8,
                                           binop(Iop_Add32,
                                                 mkexpr(t8),
                                                 mkU32(1))))),
                           unop(Iop_Not64,
                                binop(Iop_Shr64,
                                      mkU64(0xffffffffffffffffULL),
                                      unop(Iop_32to8,
                                           binop(Iop_Add32,
                                                 mkexpr(t8),
                                                 mkU32(1)))))));

         assign(t7, IRExpr_ITE(mkexpr(t3),
                               unop(Iop_64to32,
                                    binop(Iop_And64,
                                          mkexpr(t5),
                                          mkexpr(t6))),
                               binop(Iop_Shr32,
                                     unop(Iop_64HIto32,
                                          binop(Iop_And64,
                                                mkexpr(t5),
                                                mkexpr(t6))),
                                     unop(Iop_32to8,
                                          binop(Iop_Sub32,
                                                mkU32(31),
                                                mkexpr(t8))))));

         putIReg(rt, mkexpr(t7));
         break;
      }

      case 0x4: {  /* EXTR_R.W */
         DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);
         t15 = newTemp(Ity_I64);
         t16 = newTemp(Ity_I1);

         assign(t0, getAcc(ac));
         assign(t16, binop(Iop_CmpEQ32,
                           mkU32(rs),
                           mkU32(0)));
         assign(t1, IRExpr_ITE(mkexpr(t16),
                               mkexpr(t0),
                               binop(Iop_Sar64,
                                     mkexpr(t0),
                                     mkU8(rs))));
         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least significant bit of the shifted value
            from acc. */
         assign(t15, binop(Iop_Shr64,
                           mkexpr(t0),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      binop(Iop_And32,
                                            mkU32(rs),
                                            mkU32(0x1f)),
                                      mkU32(1)))));

         assign(t8,
                IRExpr_ITE(mkexpr(t16),
                           mkU64(0x0ULL),
                           binop(Iop_And64,
                                 mkexpr(t15),
                                 mkU64(0x0000000000000001ULL))));
         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
         putIReg(rt, unop(Iop_64to32, mkexpr(t9)));

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));

         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         break;
      }

      case 0x5: {  /* EXTRV_R.W */
         DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);
         t15 = newTemp(Ity_I8);

         assign(t15, unop(Iop_32to8,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0x1f))));
         assign(t0, getAcc(ac));
         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));
         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least sifgnificant bit of the shifted value
            from acc. */
         assign(t8,
                IRExpr_ITE(binop(Iop_CmpEQ32,
                                 unop(Iop_8Uto32,
                                      mkexpr(t15)),
                                 mkU32(0)),
                           mkU64(0x0ULL),
                           binop(Iop_And64,
                                 binop(Iop_Shr64,
                                       mkexpr(t0),
                                       unop(Iop_32to8,
                                            binop(Iop_Sub32,
                                                  unop(Iop_8Uto32,
                                                        mkexpr(t15)),
                                                  mkU32(1)))),
                                 mkU64(0x1ULL))));

         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
         /* Put rounded value in destination register. */
         putIReg(rt, unop(Iop_64to32, mkexpr(t9)));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         break;
      }

      case 0x6: {  /* EXTR_RS.W */
         DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);
         t16 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));

         if (0 == rs) {
            assign(t1, mkexpr(t0));
         } else {
            assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
         }

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));
         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least sifgnificant bit of the shifted value
            from acc. */
         if (0 == rs) {
            assign(t8, mkU64(0x0ULL));
         } else {
            assign(t8, binop(Iop_And64,
                             binop(Iop_Shr64,
                                   mkexpr(t0),
                                   mkU8(rs - 1)),
                             mkU64(0x1ULL)));
         }

         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         assign(t16, binop(Iop_And32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0x80000000)));
         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t14),
                                      mkU32(0)),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 mkexpr(t16),
                                                 mkU32(0)),
                                           mkU32(0x7fffffff),
                                           mkU32(0x80000000)),
                                unop(Iop_64to32, mkexpr(t9))));
         break;
      }

      case 0x7: {  /* EXTRV_RS.W */
         DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I32);
         t15 = newTemp(Ity_I32);
         t16 = newTemp(Ity_I32);
         t17 = newTemp(Ity_I1);

         assign(t15, binop(Iop_And32,
                           getIReg(rs),
                           mkU32(0x1f)));
         assign(t17, binop(Iop_CmpEQ32,
                           mkexpr(t15),
                           mkU32(0)));
         assign(t0, getAcc(ac));
         assign(t1, IRExpr_ITE(mkexpr(t17),
                               mkexpr(t0),
                               binop(Iop_Sar64,
                                     mkexpr(t0),
                                     unop(Iop_32to8,
                                          mkexpr(t15)))));

         /* Check if bits 63..31 of the result in t1 aren't 0. */
         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0)));
         /* Check if bits 63..31 of the result in t1 aren't
            0x1ffffffff. */
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32,
                               mkexpr(t1)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64to32,
                                     mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU32(0x80000000)));
         /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
            control register. */
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t3)),
                                unop(Iop_1Sto32, mkexpr(t4))),
                          binop(Iop_Or32,
                                unop(Iop_1Sto32, mkexpr(t5)),
                                unop(Iop_1Sto32, mkexpr(t6)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t7),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         /* If the last discarded bit is 1, there would be carry
            when rounding, otherwise there wouldn't. We use that
            fact and just add the value of the last discarded bit
            to the least sifgnificant bit of the shifted value
            from acc. */
         assign(t8,
                IRExpr_ITE(mkexpr(t17),
                           mkU64(0x0ULL),
                           binop(Iop_And64,
                                 binop(Iop_Shr64,
                                       mkexpr(t0),
                                       unop(Iop_32to8,
                                            binop(Iop_Sub32,
                                                  mkexpr(t15),
                                                  mkU32(1)))),
                                 mkU64(0x1ULL))));

         assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));

         /* Repeat previous steps for the rounded value. */
         assign(t10, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0)));
         assign(t11, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0)));

         assign(t12, binop(Iop_CmpNE32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0xffffffff)));
         assign(t13, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 unop(Iop_64to32,
                                      mkexpr(t9)),
                                 mkU32(0x80000000)),
                           mkU32(0x80000000)));

         assign(t14, binop(Iop_And32,
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t10)),
                                 unop(Iop_1Sto32, mkexpr(t11))),
                           binop(Iop_Or32,
                                 unop(Iop_1Sto32, mkexpr(t12)),
                                 unop(Iop_1Sto32, mkexpr(t13)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t14),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));

         assign(t16, binop(Iop_And32,
                           unop(Iop_64HIto32,
                                mkexpr(t9)),
                           mkU32(0x80000000)));
         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t14),
                                      mkU32(0)),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 mkexpr(t16),
                                                 mkU32(0)),
                                           mkU32(0x7fffffff),
                                           mkU32(0x80000000)),
                                unop(Iop_64to32, mkexpr(t9))));
         break;
      }

      case 0xA: {  /* EXTPDP */
         DIP("extpdp r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));
         /* Extract pos field of DSPControl register. */
         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));

         /* Check if (pos - size) >= 0 [size <= pos]
            if (pos < size)
               put 1 to EFI field of DSPControl register
            else
               extract bits from acc and put 0 to EFI field of
               DSPCtrl */
         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));

         assign(t8, binop(Iop_Or32,
                          binop(Iop_And32,
                                getDSPControl(),
                                mkU32(0xffffbfc0)),
                          binop(Iop_And32,
                                binop(Iop_Sub32,
                                      binop(Iop_And32,
                                            getDSPControl(),
                                            mkU32(0x3f)),
                                      mkU32(rs + 1)),
                                mkU32(0x3f))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffbfff)),
                                        mkU32(0x4000)),
                                  mkexpr(t8)));

         /* If pos <= 31, shift right the value from the acc
            (pos-size) times and take (size+1) bits from the least
            significant positions. Otherwise, shift left the value
            (63-pos) times, take (size+1) bits from the most
            significant positions and shift right (31-size) times.
         */
         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));

         assign(t4,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkexpr(t1), mkU32(rs))),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkU32(63), mkexpr(t1)))));

         assign(t5, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Shr64,
                                     mkexpr(t0), mkexpr(t4)),
                               binop(Iop_Shl64,
                                     mkexpr(t0), mkexpr(t4))));

         /* t6 holds a mask for bit extraction. */
         assign(t6,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_Not64,
                                binop(Iop_Shl64,
                                      mkU64(0xffffffffffffffffULL),
                                      mkU8(rs + 1))),
                           unop(Iop_Not64,
                                binop(Iop_Shr64,
                                      mkU64(0xffffffffffffffffULL),
                                      mkU8(rs + 1)))));

         assign(t7, IRExpr_ITE(mkexpr(t3),
                               unop(Iop_64to32,
                                    binop(Iop_And64,
                                          mkexpr(t5),
                                          mkexpr(t6))),
                               binop(Iop_Shr32,
                                     unop(Iop_64HIto32,
                                          binop(Iop_And64,
                                                mkexpr(t5),
                                                mkexpr(t6))),
                                     mkU8(31 - rs))));

         putIReg(rt, mkexpr(t7));
         break;
      }

      case 0xB: {  /* EXTPDPV */
         DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);

         assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
         assign(t0, getAcc(ac));
         /* Extract pos field of DSPControl register. */
         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));

         /* Check if (pos - size) >= 0 [size <= pos]
            if (pos < size)
               put 1 to EFI field of DSPControl register
            else
               extract bits from acc and put 0 to EFI field of
               DSPCtrl */
         assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));

         assign(t9, binop(Iop_Or32,
                          binop(Iop_And32,
                                getDSPControl(),
                                mkU32(0xffffbfc0)),
                          binop(Iop_And32,
                                binop(Iop_Sub32,
                                      binop(Iop_And32,
                                            getDSPControl(),
                                            mkU32(0x3f)),
                                      binop(Iop_Add32,
                                            mkexpr(t8),
                                            mkU32(0x1))),
                                mkU32(0x3f))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffbfff)),
                                        mkU32(0x4000)),
                                  mkexpr(t9)));

         /* If pos <= 31, shift right the value from the acc
            (pos-size) times and take (size+1) bits from the least
            significant positions. Otherwise, shift left the value
            (63-pos) times, take (size+1) bits from the most
            significant positions and shift right (31-size) times.
         */
         assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));

         assign(t4,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkexpr(t1), mkexpr(t8))),
                           unop(Iop_32to8,
                                binop(Iop_Sub32,
                                      mkU32(63), mkexpr(t1)))));

         assign(t5, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Shr64,
                                     mkexpr(t0), mkexpr(t4)),
                               binop(Iop_Shl64,
                                     mkexpr(t0), mkexpr(t4))));

         /* t6 holds a mask for bit extraction. */
         assign(t6,
                IRExpr_ITE(mkexpr(t3),
                           unop(Iop_Not64,
                                binop(Iop_Shl64,
                                      mkU64(0xffffffffffffffffULL),
                                      unop(Iop_32to8,
                                           binop(Iop_Add32,
                                                 mkexpr(t8),
                                                 mkU32(1))))),
                           unop(Iop_Not64,
                                binop(Iop_Shr64,
                                      mkU64(0xffffffffffffffffULL),
                                      unop(Iop_32to8,
                                           binop(Iop_Add32,
                                                 mkexpr(t8),
                                                 mkU32(1)))))));

         assign(t7, IRExpr_ITE(mkexpr(t3),
                               unop(Iop_64to32,
                                    binop(Iop_And64,
                                          mkexpr(t5),
                                          mkexpr(t6))),
                               binop(Iop_Shr32,
                                     unop(Iop_64HIto32,
                                          binop(Iop_And64,
                                                mkexpr(t5),
                                                mkexpr(t6))),
                                     unop(Iop_32to8,
                                          binop(Iop_Sub32,
                                                mkU32(31),
                                                mkexpr(t8))))));

         putIReg(rt, mkexpr(t7));
         break;
      }

      case 0xE: {  /* EXTR_S.H */
         DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I64);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));

         assign(t2, binop(Iop_Or32,
                          getDSPControl(), mkU32(0x00800000)));

         assign(t5, binop(Iop_And32,
                          unop(Iop_64to32,
                               mkexpr(t1)),
                          mkU32(0x80000000)));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t5),
                                        binop(Iop_And32,
                                              unop(Iop_64HIto32,
                                                    mkexpr(t0)),
                                              mkU32(0x80000000))),
                                  mkexpr(t2),
                                  getDSPControl()));

         /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
            1. subtract 0x7fff from t1
            2. if the resulting number is positive (sign bit = 0)
               and any of the other bits is 1, the value is > 0. */
         assign(t3, binop(Iop_Sub64,
                          mkexpr(t1),
                          mkU64(0x0000000000007fffULL)));
         assign(t4, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           binop(Iop_And32,
                                                 unop(Iop_64HIto32,
                                                       mkexpr(t3)),
                                                 mkU32(0x7fffffff)))),
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           unop(Iop_64to32,
                                                mkexpr(t3))))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_64HIto32,
                                                mkexpr(t3)),
                                           mkU32(0x80000000)),
                                     mkU32(0)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkU32(0),
                                        mkexpr(t4)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
            1. subtract t1 from 0xffffffffffff8000
            2. if the resulting number is positive (sign bit = 0)
                and any of the other bits is 1, the value is > 0 */
         assign(t6, binop(Iop_Sub64,
                          mkU64(0xffffffffffff8000ULL),
                          mkexpr(t1)));
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           binop(Iop_And32,
                                                 unop(Iop_64HIto32,
                                                       mkexpr(t6)),
                                                 mkU32(0x7fffffff)))),
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           unop(Iop_64to32,
                                                mkexpr(t6))))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_64HIto32,
                                                mkexpr(t6)),
                                           mkU32(0x80000000)),
                                     mkU32(0)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkU32(0),
                                        mkexpr(t7)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkU32(0),
                                      mkexpr(t4)),
                                mkU32(0x00007fff),
                                IRExpr_ITE(binop(Iop_CmpNE32,
                                                 mkU32(0),
                                                 mkexpr(t7)),
                                           mkU32(0xffff8000),
                                           unop(Iop_64to32,
                                                mkexpr(t1)))));
         break;
      }

      case 0xF: {  /* EXTRV_S.H */
         DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I64);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Sar64,
                          mkexpr(t0),
                          unop(Iop_32to8,
                               binop(Iop_And32,
                                     getIReg(rs),
                                     mkU32(0x1f)))));

         assign(t2, binop(Iop_Or32,
                          getDSPControl(), mkU32(0x00800000)));

         assign(t5, binop(Iop_And32,
                          unop(Iop_64to32,
                               mkexpr(t1)),
                          mkU32(0x80000000)));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t5),
                                        binop(Iop_And32,
                                              unop(Iop_64HIto32,
                                                    mkexpr(t0)),
                                              mkU32(0x80000000))),
                                  mkexpr(t2),
                                  getDSPControl()));

         /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
            1. subtract 0x7fff from t1
            2. if the resulting number is positive (sign bit = 0)
               and any of the other bits is 1, the value is > 0. */
         assign(t3, binop(Iop_Sub64,
                          mkexpr(t1),
                          mkU64(0x0000000000007fffULL)));
         assign(t4, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           binop(Iop_And32,
                                                 unop(Iop_64HIto32,
                                                       mkexpr(t3)),
                                                 mkU32(0x7fffffff)))),
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           unop(Iop_64to32,
                                                mkexpr(t3))))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_64HIto32,
                                                mkexpr(t3)),
                                           mkU32(0x80000000)),
                                     mkU32(0)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkU32(0),
                                        mkexpr(t4)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
            1. subtract t1 from 0xffffffffffff8000
            2. if the resulting number is positive (sign bit = 0)
                and any of the other bits is 1, the value is > 0 */
         assign(t6, binop(Iop_Sub64,
                          mkU64(0xffffffffffff8000ULL),
                          mkexpr(t1)));
         assign(t7, binop(Iop_And32,
                          binop(Iop_Or32,
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           binop(Iop_And32,
                                                 unop(Iop_64HIto32,
                                                       mkexpr(t6)),
                                                 mkU32(0x7fffffff)))),
                                unop(Iop_1Sto32,
                                     binop(Iop_CmpNE32,
                                           mkU32(0),
                                           unop(Iop_64to32,
                                                mkexpr(t6))))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_64HIto32,
                                                mkexpr(t6)),
                                           mkU32(0x80000000)),
                                     mkU32(0)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkU32(0),
                                        mkexpr(t7)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00800000)),
                                  getDSPControl()));
         putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkU32(0),
                                      mkexpr(t4)),
                                mkU32(0x00007fff),
                                IRExpr_ITE(binop(Iop_CmpNE32,
                                                 mkU32(0),
                                                 mkexpr(t7)),
                                           mkU32(0xffff8000),
                                           unop(Iop_64to32,
                                                mkexpr(t1)))));
         break;
      }

      case 0x12: {  /* RDDSP*/
         DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask);
         vassert(!mode64);

         putIReg(rd, mkU32(0x0));

         if ((rddsp_mask & 0x1) == 0x1) {
            /* Read pos field (bits 5-0) of DSPControl register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0x0000003F))));
         }

         if ((rddsp_mask & 0x2) == 0x2) {
            /* Read scount field (bits 12-7) of DSPControl
               register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0x00001F80))));
         }

         if ((rddsp_mask & 0x4) == 0x4) {
            /* Read C field (bit 13) of DSPControl register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0x00002000))));
         }

         if ((rddsp_mask & 0x8) == 0x8) {
            /* Read outflag field (bit s 23-16) of DSPControl
               register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0x00FF0000))));
         }

         if ((rddsp_mask & 0x10) == 0x10) {
            /* Read ccond field (bits 31-24) of DSPControl
               register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0xFF000000))));
         }

         if ((rddsp_mask & 0x20) == 0x20) {
            /* Read EFI field (bit 14) of DSPControl register. */
            putIReg(rd, binop(Iop_Or32,
                              getIReg(rd),
                              binop(Iop_And32,
                                    getDSPControl(),
                                    mkU32(0x00004000))));
         }

         if ((rddsp_mask & 0x3f) == 0x3f) {
            /* Read all fields of DSPControl register. */
            putIReg(rd, getDSPControl());
         }

         break;
      }

      case 0x13: {  /* WRDSP */
         DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask);
         vassert(!mode64);

         if ((wrdsp_mask & 0x3f) == 0x3f) {
            /* If mips64 put all fields of rs, except bit 15 and bit
               6, to DSPControl register, otherwise put all except
               bits 15, 6 and bits 31..28. */
            putDSPControl(mode64 ?
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0xffff7fbf)) :
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0x0fff7fbf)));
         } else {
            if ((wrdsp_mask & 0x1) == 0x1) {
               /* Put bits 5-0 of rs to DSPControl register pos
                  field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0xFFFF7F40)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mkU32(0x0000003F))));
            }

            if ((wrdsp_mask & 0x2) == 0x2) {
               /* Put bits 12-7 of rs to DSPControl scount field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0xFFFFE03F)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mkU32(0x00001F80))));
            }

            if ((wrdsp_mask & 0x4) == 0x4) {
               /* Put bit 13 of rs to DSPControl register C
                  field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0xFFFF5FBF)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mkU32(0x00002000))));
            }

            if ((wrdsp_mask & 0x8) == 0x8) {
               /* Put bits 23-16 of rs to DSPControl reg outflag
                  field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0xFF007FBF)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mkU32(0x00FF0000))));
            }

            if ((wrdsp_mask & 0x10) == 0x10) {
               /* Put bits 31-24 of rs to DSPControl reg ccond
                  field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0x00FF7FBF)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mode64 ? mkU32(0xFF000000)
                                         : mkU32(0x0F000000))
                                  )
                            );
            }

            if ((wrdsp_mask & 0x20) == 0x20) {
               /* Put bit 14 of rs to DSPControl register EFI
                  field. */
               putDSPControl(binop(Iop_Or32,
                                   binop(Iop_And32,
                                         getDSPControl(),
                                         mkU32(0xFFFF3FBF)),
                                   binop(Iop_And32,
                                         getIReg(rs),
                                         mkU32(0x00004000))));
            }
         }

         break;
      }

      case 0x1A: {  /* SHILO */
         DIP("shilo ac%u, %u", ac, shift);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));

         putAcc(ac, mkexpr(t0));

         if (0x20 == (shift & 0x3f)) {
            putAcc(ac, binop(Iop_32HLto64,
                             unop(Iop_64to32, mkexpr(t0)),
                             mkU32(0x0)));
         } else if (0x20 == (shift & 0x20)) {
            assign(t1, binop(Iop_Shl64,
                             mkexpr(t0),
                             unop(Iop_32to8,
                                  binop(Iop_Add32,
                                        unop(Iop_Not32,
                                             mkU32(shift)),
                                        mkU32(0x1)))));

            putAcc(ac, mkexpr(t1));
         } else {
            assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));

            putAcc(ac, mkexpr(t1));
         }

         break;
      }

      case 0x1B: {  /* SHILOV */
         DIP("shilov ac%u, r%u", ac, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I64);
         t4 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));
         assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
         assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
         assign(t3, binop(Iop_Shl64,
                          mkexpr(t0),
                          unop(Iop_32to8,
                               binop(Iop_Add32,
                                     unop(Iop_Not32,
                                          mkexpr(t1)),
                                     mkU32(0x1)))));
         assign(t4, binop(Iop_Shr64,
                          mkexpr(t0),
                          unop(Iop_32to8,
                               mkexpr(t1))));

         putAcc(ac,
                IRExpr_ITE(mkexpr(t2),
                           binop(Iop_32HLto64,
                                 unop(Iop_64to32, mkexpr(t0)),
                                 mkU32(0x0)),
                           IRExpr_ITE(binop(Iop_CmpEQ32,
                                            binop(Iop_And32,
                                                  mkexpr(t1),
                                                  mkU32(0x20)),
                                            mkU32(0x20)),
                                      mkexpr(t3),
                                      mkexpr(t4))));
         break;
      }

      case 0x1F: {  /* MTHLIP */
         DIP("mthlip r%u, ac%u", rs, ac);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));
         putAcc(ac, binop(Iop_32HLto64,
                          unop(Iop_64to32, mkexpr(t0)),
                          getIReg(rs)));
         assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
                                        mkU32(32),
                                        mkexpr(t1)),
                                  binop(Iop_Or32,
                                        binop(Iop_Sub32,
                                              mkexpr(t1),
                                              mkU32(32)),
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffffc0))),
                                  binop(Iop_Or32,
                                        binop(Iop_Add32,
                                              mkexpr(t1),
                                              mkU32(32)),
                                        binop(Iop_And32,
                                              getDSPControl(),
                                              mkU32(0xffffffc0)))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_LX( UInt cins )
{
   IRTemp t0;
   UInt   rs, rt, rd, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x0: {  /* LWX */
         DIP("lwx r%u, r%u(r%u)", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));

         putIReg(rd, load(Ity_I32, mkexpr(t0)));
         break;
      }

      case 0x4: {  /* LHX */
         DIP("lhx r%u, r%u(r%u)", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));

         putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
         break;
      }

      case 0x6: {  /* LBUX */
         DIP("lbux r%u, r%u(r%u)", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));

         putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_INSV( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t6, t7, t8;
   UInt   rs, rt, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x0: {  /* INSV */
         DIP("insv r%u, r%u", rt, rs);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         /* t0 <- pos field of DSPControl register. */
         assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
         /* t1 <- scount field of DSPControl register. */
         assign(t1, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getDSPControl(),
                                mkU32(0x1f80)),
                          mkU8(7)));

         assign(t2, unop(Iop_32to8,
                         binop(Iop_Add32,
                               mkexpr(t1),
                               mkexpr(t0))));

         /* 32-(pos+size) most significant bits of rt. */
         assign(t6, binop(Iop_Shl32,
                          binop(Iop_Shr32,
                                getIReg(rt),
                                mkexpr(t2)),
                          mkexpr(t2)));

         assign(t3, unop(Iop_32to8,
                         binop(Iop_Sub32,
                               mkU32(32),
                               mkexpr(t0))));
         /* Pos least significant bits of rt. */
         assign(t7, binop(Iop_Shr32,
                          binop(Iop_Shl32,
                                getIReg(rt),
                                mkexpr(t3)),
                          mkexpr(t3)));

         /* Size least significant bits of rs,
            shifted to appropriate position. */
         assign(t8, binop(Iop_Shl32,
                          binop(Iop_And32,
                                getIReg(rs),
                                unop(Iop_Not32,
                                     binop(Iop_Shl32,
                                           mkU32(0xffffffff),
                                           unop(Iop_32to8,
                                                mkexpr(t1))))),
                          unop(Iop_32to8,
                               mkexpr(t0))));

         putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      mkexpr(t0),
                                      mkU32(0)),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 mkexpr(t1),
                                                 mkU32(32)),
                                           getIReg(rs),
                                           binop(Iop_Or32,
                                                 mkexpr(t6),
                                                 mkexpr(t8))),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 unop(Iop_8Uto32,
                                                       mkexpr(t2)),
                                                 mkU32(32)),
                                           binop(Iop_Or32,
                                                 mkexpr(t7),
                                                 mkexpr(t8)),
                                           binop(Iop_Or32,
                                                 binop(Iop_Or32,
                                                       mkexpr(t6),
                                                       mkexpr(t7)),
                                                 mkexpr(t8)))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_ADDU_QB( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
   UInt   rs, rt, rd, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x00: {  /* ADDU.QB */
         DIP("addu.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I32);

         /* Add rightmost bytes of rs and rt. */
         assign(t0,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t1 will be 1 if there is overflow, 0 otherwise. */
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Add bits 15-8 of rs and rt. */
         assign(t2,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t3 will be 1 if there is overflow, 0 otherwise. */
         assign(t3, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t2),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Add bits 15-8 of rs and rt. */
         assign(t4,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t5 will be 1 if there is overflow, 0 otherwise. */
         assign(t5, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t4),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Add bits 15-8 of rs and rt. */
         assign(t6,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t7 will be 1 if there is overflow, 0 otherwise. */
         assign(t7, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t6),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         assign(t8,
                binop(Iop_Or32,
                      binop(Iop_Or32,
                            binop(Iop_Or32,
                                  unop(Iop_1Sto32, mkexpr(t7)),
                                  unop(Iop_1Sto32,  mkexpr(t5))),
                            unop(Iop_1Sto32, mkexpr(t3))),
                      unop(Iop_1Sto32, mkexpr(t1))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t8),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000))));

         putIReg(rd, binop(Iop_16HLto32,
                           binop(Iop_8HLto16,
                                 unop(Iop_32to8, mkexpr(t6)),
                                 unop(Iop_32to8, mkexpr(t4))),
                           binop(Iop_8HLto16,
                                 unop(Iop_32to8, mkexpr(t2)),
                                 unop(Iop_32to8, mkexpr(t0)))));
         break;
      }

      case 0x1: {  /* SUBU.QB */
         DIP("subu.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I32);

         /* Subtract rightmost bytes of rs and rt. */
         assign(t0,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t1 will be 1 if there is overflow, 0 otherwise. */
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Subtract bits 15-8 of rs and rt. */
         assign(t2,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t3 will be 1 if there is overflow, 0 otherwise. */
         assign(t3, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t2),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Subtract bits 15-8 of rs and rt. */
         assign(t4,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t5 will be 1 if there is overflow, 0 otherwise. */
         assign(t5, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t4),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         /* Subtract bits 15-8 of rs and rt. */
         assign(t6,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t7 will be 1 if there is overflow, 0 otherwise. */
         assign(t7, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t6),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));

         assign(t8, binop(Iop_Or32,
                          binop(Iop_Or32,
                                binop(Iop_Or32,
                                      unop(Iop_1Sto32, mkexpr(t7)),
                                      unop(Iop_1Sto32, mkexpr(t5))),
                                unop(Iop_1Sto32, mkexpr(t3))),
                          unop(Iop_1Sto32, mkexpr(t1))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t8),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000))));

         putIReg(rd, binop(Iop_16HLto32,
                           binop(Iop_8HLto16,
                                 unop(Iop_32to8, mkexpr(t6)),
                                 unop(Iop_32to8, mkexpr(t4))),
                           binop(Iop_8HLto16,
                                 unop(Iop_32to8, mkexpr(t2)),
                                 unop(Iop_32to8, mkexpr(t0)))));
         break;
      }

      case 0x04: {  /* ADDU_S.QB */
         DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I8);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I8);
         t12 = newTemp(Ity_I32);

         /* Add rightmost bytes of rs and rt. */
         assign(t0,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t1 will be 1 if there is overflow, 0 otherwise. */
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         /* Saturate if necessary. */
         assign(t2, IRExpr_ITE(mkexpr(t1),
                               mkU8(0xff),
                               unop(Iop_32to8, mkexpr(t0))));

         /* Add bits 15-8 of rs and rt. */
         assign(t3,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* t4 will be 1 if there is overflow, 0 otherwise. */
         assign(t4, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t3),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         /* Saturate if necessary. */
         assign(t5, IRExpr_ITE(mkexpr(t4),
                               mkU8(0xff),
                               unop(Iop_32to8, mkexpr(t3))));

         /* Add bits 15-8 of rs and rt. */
         assign(t6,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t7 will be 1 if there is overflow, 0 otherwise. */
         assign(t7, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t6),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         /* Saturate if necessary. */
         assign(t8, IRExpr_ITE(mkexpr(t7),
                               mkU8(0xff),
                               unop(Iop_32to8, mkexpr(t6))));

         /* Add bits 15-8 of rs and rt. */
         assign(t9,
                binop(Iop_Add32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         /* t10 will be 1 if there is overflow, 0 otherwise. */
         assign(t10, binop(Iop_CmpEQ32,
                           binop(Iop_And32,
                                 mkexpr(t9),
                                 mkU32(0x00000100)),
                           mkU32(0x00000100)));
         /* Saturate if necessary. */
         assign(t11, IRExpr_ITE(mkexpr(t10),
                                mkU8(0xff),
                                unop(Iop_32to8, mkexpr(t9))));

         assign(t12,
                binop(Iop_Or32,
                      binop(Iop_Or32,
                            binop(Iop_Or32,
                                  unop(Iop_1Sto32, mkexpr(t10)),
                                  unop(Iop_1Sto32, mkexpr(t7))),
                            unop(Iop_1Sto32, mkexpr(t4))),
                      unop(Iop_1Sto32, mkexpr(t1))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t12),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000))));

         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
                       binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
         break;
      }

      case 0x05: {  /* SUBU_S.QB */
         DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);

         /* Use C function to easily calculate the result
            and write it in the register more conveniently
            Underflow is checked using step by step subtraction. */
         assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));

         /* Subtract each byte of rs and rt. */
         assign(t6,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t7,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t8,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t9,
                binop(Iop_Sub32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));

         /* Put 1 to bit 20 in DSPControl if there is underflow
            in either byte. */
         assign(t2, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t6),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         assign(t3, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t7),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         assign(t4, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t8),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         assign(t5, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                mkexpr(t9),
                                mkU32(0x00000100)),
                          mkU32(0x00000100)));
         putDSPControl(IRExpr_ITE(mkexpr(t5),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         putIReg(rd, mkexpr(t1));
         break;
      }

      case 0x6: {  /* MULEU_S.PH.QBL */
         DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);

         assign(t0,
                unop(Iop_64to32,
                     binop(Iop_MullU32,
                           unop(Iop_8Uto32,
                                unop(Iop_16HIto8,
                                     unop(Iop_32HIto16,
                                          getIReg(rs)))),
                           unop(Iop_16Uto32,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t1,
                unop(Iop_64to32,
                     binop(Iop_MullU32,
                           unop(Iop_8Uto32,
                                unop(Iop_16to8,
                                     unop(Iop_32HIto16,
                                          getIReg(rs)))),
                           unop(Iop_16Uto32,
                                unop(Iop_32to16, getIReg(rt))))));

         assign(t2, binop(Iop_CmpNE32,
                          mkU32(0x0),
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x03ff0000))));
         assign(t3, binop(Iop_CmpNE32,
                          mkU32(0x0),
                          binop(Iop_And32,
                                mkexpr(t1),
                                mkU32(0x03ff0000))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x200000)),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x200000)),
                                             getDSPControl())));
         putIReg(rd,
                 binop(Iop_16HLto32,
                       IRExpr_ITE(mkexpr(t2),
                                  mkU16(0xffff),
                                  unop(Iop_32to16, mkexpr(t0))),
                       IRExpr_ITE(mkexpr(t3),
                                  mkU16(0xffff),
                                  unop(Iop_32to16, mkexpr(t1)))));
         break;
      }

      case 0x7: {  /* MULEU_S.PH.QBR */
         DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);

         assign(t0, unop(Iop_64to32,
                         binop(Iop_MullU32,
                               unop(Iop_8Uto32,
                                    unop(Iop_16HIto8,
                                         unop(Iop_32to16,
                                              getIReg(rs)))),
                               unop(Iop_16Uto32,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t1, unop(Iop_64to32,
                         binop(Iop_MullU32,
                               unop(Iop_8Uto32,
                                    unop(Iop_16to8,
                                         unop(Iop_32to16,
                                              getIReg(rs)))),
                               unop(Iop_16Uto32,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));

         assign(t2, binop(Iop_CmpNE32,
                          mkU32(0x0),
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x03ff0000))));
         assign(t3, binop(Iop_CmpNE32,
                          mkU32(0x0),
                          binop(Iop_And32,
                                mkexpr(t1),
                                mkU32(0x03ff0000))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x200000)),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x200000)),
                                             getDSPControl())));
         putIReg(rd, binop(Iop_16HLto32,
                           IRExpr_ITE(mkexpr(t2),
                                      mkU16(0xffff),
                                      unop(Iop_32to16,
                                           mkexpr(t0))),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU16(0xffff),
                                      unop(Iop_32to16,
                                           mkexpr(t1)))));
         break;
      }

      case 0x08: {  /* ADDU.PH */
         DIP("addu.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);

         /* Add lower halves. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Detect overflow. */
         assign(t1, binop(Iop_CmpLT32U,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, mkexpr(t0))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs)))));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Add higher halves. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Detect overflow. */
         assign(t3, binop(Iop_CmpLT32U,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, mkexpr(t2))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16,
                                    getIReg(rs)))));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t2)),
                           unop(Iop_32to16, mkexpr(t0))));
         break;
      }

      case 0x9: {  /* SUBU.PH */
         DIP("subu.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);

         /* Substract lower halves. */
         assign(t0, binop(Iop_Sub32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Detect underflow. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x00010000)),
                          mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Subtract higher halves. */
         assign(t2, binop(Iop_Sub32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Detect underflow. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t2),
                                mkU32(0x00010000)),
                          mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t2)),
                           unop(Iop_32to16, mkexpr(t0))));
         break;
      }

      case 0xA: {  /* ADDQ.PH */
         DIP("addq.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);

         /* Add lower halves. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t6, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t0))),
                          mkU32(0x1)));
         /* Detect overflow. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t0),
                                      mkU32(0x8000)),
                                mkU8(15)),
                          mkexpr(t6)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Add higher halves. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t7, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x1)));
         /* Detect overflow. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0x00008000)),
                                mkU8(15)),
                          mkexpr(t7)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t2)),
                           unop(Iop_32to16, mkexpr(t0))));
         break;
      }

      case 0xB: {  /* SUBQ.PH */
         DIP("subq.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);

         /* Subtract lower halves. */
         assign(t0, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t6, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t0))),
                          mkU32(0x1)));
         /* Compare the signs of input value and the result. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t0),
                                      mkU32(0x8000)),
                                mkU8(15)),
                          mkexpr(t6)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Subtract higher halves. */
         assign(t2, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t7, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x1)));
         /* Compare the signs of input value and the result. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0x00008000)),
                                mkU8(15)),
                          mkexpr(t7)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t2)),
                           unop(Iop_32to16, mkexpr(t0))));
         break;
      }

      case 0xC: {  /* ADDU_S.PH */
         DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);

         /* Add lower halves. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Detect overflow. */
         assign(t1, binop(Iop_CmpLT32U,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, mkexpr(t0))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs)))));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Add higher halves. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Detect overflow. */
         assign(t3, binop(Iop_CmpLT32U,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, mkexpr(t2))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs)))));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, binop(Iop_16HLto32,
                           IRExpr_ITE(mkexpr(t3),
                                      mkU16(0xffff),
                                      unop(Iop_32to16,
                                           mkexpr(t2))),
                           IRExpr_ITE(mkexpr(t1),
                                      mkU16(0xffff),
                                      unop(Iop_32to16,
                                           mkexpr(t0)))));
         break;
      }

      case 0xD: {  /* SUBU_S.PH */
         DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);

         /* Subtract lower halves. */
         assign(t0, binop(Iop_Sub32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Detect underflow. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0), mkU32(0x00010000)),
                          mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         /* Subtract higher halves. */
         assign(t2, binop(Iop_Sub32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Detect underflow. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t2), mkU32(0x00010000)),
                          mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd,
                 binop(Iop_16HLto32,
                       IRExpr_ITE(mkexpr(t3),
                                  mkU16(0x0000),
                                  unop(Iop_32to16, mkexpr(t2))),
                       IRExpr_ITE(mkexpr(t1),
                                  mkU16(0x0000),
                                  unop(Iop_32to16, mkexpr(t0)))));
         break;
      }

      case 0xE: {  /* ADDQ_S.PH */
         DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I16);
         t5 = newTemp(Ity_I16);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);

         /* Add lower halves. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t6, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t0))),
                          mkU32(0x1)));
         /* Detect overflow. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t0),
                                      mkU32(0x8000)),
                                mkU8(15)),
                          mkexpr(t6)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         /* Saturate if needed. */
         assign(t4, IRExpr_ITE(mkexpr(t1),
                               IRExpr_ITE(binop(Iop_CmpEQ32,
                                                mkexpr(t6),
                                                mkU32(0x0)),
                                          mkU16(0x7fff),
                                          mkU16(0x8000)),
                               unop(Iop_32to16, mkexpr(t0))));

         /* Add higher halves. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t7, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x1)));
         /* Detect overflow. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0x00008000)),
                                mkU8(15)),
                          mkexpr(t7)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         /* Saturate if needed. */
         assign(t5, IRExpr_ITE(mkexpr(t3),
                               IRExpr_ITE(binop(Iop_CmpEQ32,
                                                mkexpr(t7),
                                                mkU32(0x0)),
                                          mkU16(0x7fff),
                                          mkU16(0x8000)),
                               unop(Iop_32to16, mkexpr(t2))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
         break;
      }

      case 0xF: {  /* SUBQ_S.PH */
         DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I16);
         t5 = newTemp(Ity_I16);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);

         /* Subtract lower halves. */
         assign(t0, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t6, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t0))),
                          mkU32(0x1)));
         /* Detect overflow or underflow. */
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t0),
                                      mkU32(0x8000)),
                                mkU8(15)),
                          mkexpr(t6)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         /* Saturate if needed. */
         assign(t4, IRExpr_ITE(mkexpr(t1),
                               IRExpr_ITE(binop(Iop_CmpEQ32,
                                                mkexpr(t6),
                                                mkU32(0x0)),
                                          mkU16(0x7fff),
                                          mkU16(0x8000)),
                               unop(Iop_32to16, mkexpr(t0))));

         /* Subtract higher halves. */
         assign(t2, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));

         /* Bit 16 of the result. */
         assign(t7, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x1)));
         /* Detect overflow or underflow. */
         assign(t3, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      mkexpr(t2),
                                      mkU32(0x00008000)),
                                mkU8(15)),
                          mkexpr(t7)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         /* Saturate if needed. */
         assign(t5, IRExpr_ITE(mkexpr(t3),
                               IRExpr_ITE(binop(Iop_CmpEQ32,
                                                mkexpr(t7),
                                                mkU32(0x0)),
                                          mkU16(0x7fff),
                                          mkU16(0x8000)),
                               unop(Iop_32to16, mkexpr(t2))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
         break;
      }

      case 0x10: {  /* ADDSC */
         DIP("addsc r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);

         /* The carry bit result out of the addition operation is
            written to bit 13(the c field) of the DSPControl reg. */
         assign(t0, binop(Iop_Add64,
                          unop(Iop_32Uto64, getIReg(rs)),
                          unop(Iop_32Uto64, getIReg(rt))));

         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t0)),
                                mkU32(0x1)),
                          mkU32(0x1)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x2000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xffffdfff))));

         putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
         break;
      }

      case 0x11: {  /* ADDWC */
         DIP("addwc r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I1);

         /* Get carry bit from DSPControl register. */
         assign(t0, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getDSPControl(),
                                mkU32(0x2000)),
                          mkU8(0xd)));
         assign(t1, binop(Iop_Add64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64,
                               binop(Iop_Add32,
                                     getIReg(rt),
                                     mkexpr(t0)))));

         /* Extract bits 32 and 31. */
         assign(t2, binop(Iop_And32,
                          unop(Iop_64HIto32, mkexpr(t1)),
                          mkU32(0x1)));
         assign(t3, binop(Iop_Shr32,
                          binop(Iop_And32,
                                unop(Iop_64to32, mkexpr(t1)),
                                mkU32(0x80000000)),
                          mkU8(31)));
         assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));

         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));
         putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
         break;
      }

      case 0x12: {  /* MODSUB */
         DIP("modsub r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);

         /* decr_7..0 */
         assign(t0,
                unop(Iop_8Uto32,
                     unop(Iop_16to8,
                          unop(Iop_32to16, getIReg(rt)))));

         /* lastindex_15..0 */
         assign(t1,
                unop(Iop_16Uto32,
                     binop(Iop_8HLto16,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))),
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         /* temp_15..0 */
         assign(t2,
                IRExpr_ITE(binop(Iop_CmpEQ32,
                                 getIReg(rs),
                                 mkU32(0x00000000)),
                           mkexpr(t1),
                           binop(Iop_Sub32,
                                 getIReg(rs), mkexpr(t0))));
         putIReg(rd, mkexpr(t2));
         break;
      }

      case 0x14: {  /* RADDU.W.QB */
         DIP("raddu.w.qb r%u, r%u", rd, rs);
         vassert(!mode64);
         putIReg(rd, binop(Iop_Add32,
                           binop(Iop_Add32,
                                 unop(Iop_8Uto32,
                                      unop(Iop_16to8,
                                           unop(Iop_32to16,
                                                getIReg(rs)))),
                                 unop(Iop_8Uto32,
                                      unop(Iop_16HIto8,
                                           unop(Iop_32to16,
                                                getIReg(rs))))),
                           binop(Iop_Add32,
                                 unop(Iop_8Uto32,
                                      unop(Iop_16to8,
                                           unop(Iop_32HIto16,
                                                getIReg(rs)))),
                                 unop(Iop_8Uto32,
                                      unop(Iop_16HIto8,
                                           unop(Iop_32HIto16,
                                                getIReg(rs)))))));
         break;
      }

      case 0x16: {  /* ADDQ_S.W */
         DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Add64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));

         assign(t2, binop(Iop_And32,
                          unop(Iop_64HIto32, mkexpr(t0)),
                          mkU32(0x1)));
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t0)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          mkexpr(t2)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 mkexpr(t2),
                                                 mkU32(0x0)),
                                           mkU32(0x7fffffff),
                                           mkU32(0x80000000)),
                                unop(Iop_64to32, mkexpr(t0))));
         break;
      }

      case 0x17: {  /* SUBQ_S.W */
         DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Sub64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));

         assign(t2, binop(Iop_And32,
                          unop(Iop_64HIto32, mkexpr(t0)),
                          mkU32(0x1)));
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t0)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          mkexpr(t2)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00100000)),
                                  getDSPControl()));

         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(binop(Iop_CmpEQ32,
                                                 mkexpr(t2),
                                                 mkU32(0x0)),
                                           mkU32(0x7fffffff),
                                           mkU32(0x80000000)),
                                unop(Iop_64to32, mkexpr(t0))));
         break;
      }

      case 0x1C: {  /* MULEQ_S.W.PHL */
         DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I32);

         assign(t0,
                binop(Iop_Shl32,
                      binop(Iop_Mul32,
                            unop(Iop_16Sto32,
                                 unop(Iop_32HIto16, getIReg(rt))),
                            unop(Iop_16Sto32,
                                 unop(Iop_32HIto16, getIReg(rs)))),
                      mkU8(0x1)));
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0xffff0000)),
                          mkU32(0x80000000)));
         assign(t2, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0xffff0000)),
                          mkU32(0x80000000)));
         assign(t3, IRExpr_ITE(mkexpr(t1),
                               IRExpr_ITE(mkexpr(t2),
                                          binop(Iop_Or32,
                                                getDSPControl(),
                                                mkU32(0x00200000)),
                                          getDSPControl()),
                               getDSPControl()));
         putDSPControl(mkexpr(t3));

         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(mkexpr(t2),
                                           mkU32(0x7fffffff),
                                           mkexpr(t0)),
                                mkexpr(t0)));
         break;
      }

      case 0x1D: {  /* MULEQ_S.W.PHR */
         DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t0,
                binop(Iop_Shl32,
                      binop(Iop_Mul32,
                            unop(Iop_16Sto32,
                                 unop(Iop_32to16, getIReg(rt))),
                            unop(Iop_16Sto32,
                                 unop(Iop_32to16, getIReg(rs)))),
                      mkU8(0x1)));
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0xffff)),
                          mkU32(0x8000)));
         assign(t2, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0xffff)),
                          mkU32(0x8000)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  IRExpr_ITE(mkexpr(t2),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(mkexpr(t2),
                                           mkU32(0x7fffffff),
                                           mkexpr(t0)),
                                mkexpr(t0)));
         break;
      }

      case 0x1E: {  /* MULQ_S.PH */
         DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I16);
         t3 = newTemp(Ity_I16);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t5,
                unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
         assign(t6,
                unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));

         assign(t7,
                unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
         assign(t8,
                unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));

         assign(t0, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t5),
                                           mkU32(0xffff)),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t6),
                                           mkU32(0xffff)),
                                     mkU32(0x8000)))));
         assign(t1, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t7),
                                           mkU32(0xffff)),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t8),
                                           mkU32(0xffff)),
                                     mkU32(0x8000)))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        binop(Iop_Or32,
                                              mkexpr(t0),
                                              mkexpr(t1)),
                                        mkU32(0x0)),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x200000))));

         assign(t2, unop(Iop_32HIto16,
                         binop(Iop_Shl32,
                               unop(Iop_64to32,
                                    binop(Iop_MullS32,
                                          mkexpr(t7),
                                          mkexpr(t8))),
                               mkU8(0x1))));
         assign(t3, unop(Iop_32HIto16,
                         binop(Iop_Shl32,
                               unop(Iop_64to32,
                                    binop(Iop_MullS32,
                                          mkexpr(t5),
                                          mkexpr(t6))),
                               mkU8(0x1))));
         putIReg(rd, binop(Iop_16HLto32,
                           IRExpr_ITE(binop(Iop_CmpEQ32,
                                            mkexpr(t1),
                                            mkU32(0x0)),
                                      mkexpr(t2),
                                      mkU16(0x7fff)),
                           IRExpr_ITE(binop(Iop_CmpEQ32,
                                            mkexpr(t0),
                                            mkU32(0x0)),
                                      mkexpr(t3),
                                      mkU16(0x7fff))));
         break;
      }

      case 0x1F: {  /* MULQ_RS.PH */
         DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I16);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I16);

         /* Multiply and round lower halfwords. */
         assign(t0, binop(Iop_Add32,
                          binop(Iop_Shl32,
                                binop(Iop_Mul32,
                                      unop(Iop_16Sto32,
                                           unop(Iop_32to16,
                                                getIReg(rt))),
                                      unop(Iop_16Sto32,
                                           unop(Iop_32to16,
                                                getIReg(rs)))),
                                mkU8(0x1)),
                          mkU32(0x00008000)));
         assign(t1, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rt), mkU32(0xffff)),
                          mkU32(0x8000)));
         assign(t2, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rs), mkU32(0xffff)),
                          mkU32(0x8000)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  IRExpr_ITE(mkexpr(t2),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         assign(t3, IRExpr_ITE(mkexpr(t1),
                               IRExpr_ITE(mkexpr(t2),
                                          mkU16(0x7fff),
                                          unop(Iop_32HIto16,
                                               mkexpr(t0))),
                               unop(Iop_32HIto16, mkexpr(t0))));

         /* Multiply and round higher halfwords. */
         assign(t4, binop(Iop_Add32,
                          binop(Iop_Shl32,
                                binop(Iop_Mul32,
                                      unop(Iop_16Sto32,
                                           unop(Iop_32HIto16,
                                                getIReg(rt))),
                                      unop(Iop_16Sto32,
                                           unop(Iop_32HIto16,
                                                getIReg(rs)))),
                                mkU8(0x1)),
                          mkU32(0x00008000)));
         assign(t5, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0xffff0000)),
                          mkU32(0x80000000)));
         assign(t6, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0xffff0000)),
                          mkU32(0x80000000)));
         putDSPControl(IRExpr_ITE(mkexpr(t5),
                                  IRExpr_ITE(mkexpr(t6),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)),
                                             getDSPControl()),
                                  getDSPControl()));
         assign(t7, IRExpr_ITE(mkexpr(t5),
                               IRExpr_ITE(mkexpr(t6),
                                          mkU16(0x7fff),
                                          unop(Iop_32HIto16,
                                               mkexpr(t4))),
                               unop(Iop_32HIto16, mkexpr(t4))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_CMPU_EQ_QB( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
              t15;
   UInt   rs, rt, rd, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x0: {  /* CMPU.EQ.QB */
         DIP("cmpu.eq.qb r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);

         assign(t1,
                binop(Iop_CmpEQ32,
                      binop(Iop_And32, getIReg(rs), mkU32(0xff)),
                      binop(Iop_And32, getIReg(rt), mkU32(0xff))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));
         break;
      }

      case 0x1: {  /* CMPU.LT.QB */
         DIP("cmpu.lt.qb r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);

         assign(t1, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));
         break;
      }

      case 0x2: {  /* CMPU.LE.QB */
         DIP("cmpu.le.qb r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);

         assign(t1, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));
         break;
      }

      case 0x3: {  /* PICK.QB */
         DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I8);

         assign(t0, getDSPControl());
         assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x01000000)),
                                     mkU32(0x0)),
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rs))),
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt)))));
         assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x02000000)),
                                     mkU32(0x0)),
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs))),
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt)))));
         assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x04000000)),
                                     mkU32(0x0)),
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs))),
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt)))));
         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x08000000)),
                                     mkU32(0x0)),
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs))),
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt)))));
         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
                       binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
         break;
      }

      case 0x4: {  /* CMPGU.EQ.QB */
         DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001), mkU32(0)));

         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));

         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));

         assign(t4, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      case 0x5: {  /* CMPGU.LT.QB */
         DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001), mkU32(0)));

         assign(t2, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));

         assign(t3, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));

         assign(t4, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));
         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      case 0x6: {  /* CMPGU.LE.QB */
         DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001), mkU32(0)));

         assign(t2, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));

         assign(t3, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));

         assign(t4, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));
         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      case 0x8: {  /* CMP.EQ.PH */
         DIP("cmp.eq.ph r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t1, binop(Iop_CmpEQ16,
                          unop(Iop_32to16, getIReg(rs)),
                          unop(Iop_32to16, getIReg(rt))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));
         assign(t2, binop(Iop_CmpEQ16,
                          unop(Iop_32HIto16, getIReg(rs)),
                          unop(Iop_32HIto16, getIReg(rt))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));
         break;
      }

      case 0x9: {  /* CMP.LT.PH */
         DIP("cmp.lt.ph r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t1, binop(Iop_CmpLT32S,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLT32S,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));
         break;
      }

      case 0xA: {  /* CMP.LE.PH */
         DIP("cmp.le.ph r%u, r%u", rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t1, binop(Iop_CmpLE32S,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLE32S,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));
         break;
      }

      case 0xB: {  /* PICK.PH */
         DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I16);
         t2 = newTemp(Ity_I16);

         assign(t0, getDSPControl());

         assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x01000000)),
                                     mkU32(0x0)),
                               unop(Iop_32to16, getIReg(rs)),
                               unop(Iop_32to16, getIReg(rt))));

         assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0x02000000)),
                                     mkU32(0x0)),
                               unop(Iop_32HIto16, getIReg(rs)),
                               unop(Iop_32HIto16, getIReg(rt))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
         break;
      }

      case 0xC: {  /* PRECRQ.QB.PH */
         DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt);
         vassert(!mode64);
         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16,
                             unop(Iop_16HIto8,
                                  unop(Iop_32HIto16, getIReg(rs))),
                             unop(Iop_16HIto8,
                                  unop(Iop_32to16, getIReg(rs)))),
                       binop(Iop_8HLto16,
                             unop(Iop_16HIto8,
                                  unop(Iop_32HIto16, getIReg(rt))),
                             unop(Iop_16HIto8,
                                  unop(Iop_32to16, getIReg(rt))))));
         break;
      }

      case 0xD: {  /* PRECR.QB.PH */
         DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);

         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16,
                             unop(Iop_16to8,
                                  unop(Iop_32HIto16, getIReg(rs))),
                             unop(Iop_16to8,
                                  unop(Iop_32to16, getIReg(rs)))),
                       binop(Iop_8HLto16,
                             unop(Iop_16to8,
                                  unop(Iop_32HIto16, getIReg(rt))),
                             unop(Iop_16to8,
                                  unop(Iop_32to16, getIReg(rt))))));
         break;
      }

      case 0xF: {  /* PRECRQU_S.QB.PH */
         DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I8);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I8);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I8);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I8);
         t11 = newTemp(Ity_I1);
         t12 = newTemp(Ity_I32);
         t13 = newTemp(Ity_I8);
         t14 = newTemp(Ity_I1);
         t15 = newTemp(Ity_I32);

         assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
                                     mkU32(0x7f80),
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32to16,
                                                      getIReg(rs))),
                                           mkU32(0x7fff))),
                               mkU8(0xff),
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         binop(Iop_Shl32,
                                               getIReg(rs),
                                               mkU8(1))))));
         assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32to16,
                                                      getIReg(rs))),
                                           mkU32(0x00008000)),
                                     mkU32(0x0)),
                               mkexpr(t4),
                               mkU8(0x0)));
         assign(t5, binop(Iop_And32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16,
                                    getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t6, binop(Iop_CmpLT32U,
                          mkU32(0x7f80),
                          binop(Iop_And32,
                                unop(Iop_16Uto32,
                                     unop(Iop_32to16,
                                          getIReg(rs))),
                                mkU32(0x7fff))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        mkexpr(t5),
                                        mkU32(0x0)),
                                  IRExpr_ITE(mkexpr(t6),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00400000)
                                                  ),
                                             getDSPControl()),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00400000))));

         assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
                                     mkU32(0x7f80),
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32HIto16,
                                                      getIReg(rs))),
                                           mkU32(0x7fff))),
                               mkU8(0xff),
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         binop(Iop_Shl32,
                                               getIReg(rs),
                                               mkU8(1))))));
         assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32HIto16,
                                                      getIReg(rs))),
                                           mkU32(0x00008000)),
                                     mkU32(0x0)),
                               mkexpr(t7),
                               mkU8(0x0)));
         assign(t8, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                unop(Iop_16Uto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rs))),
                                mkU32(0x00008000)),
                          mkU32(0x0)));
         assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
                                     mkU32(0x7f80),
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32HIto16,
                                                      getIReg(rs))),
                                           mkU32(0x7fff))),
                               binop(Iop_Or32,
                                     getDSPControl(),
                                     mkU32(0x00400000)),
                               getDSPControl()));
         putDSPControl(IRExpr_ITE(mkexpr(t8),
                                  mkexpr(t9),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00400000))));

         assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
                                      mkU32(0x7f80),
                                      binop(Iop_And32,
                                            unop(Iop_16Uto32,
                                                 unop(Iop_32to16,
                                                       getIReg(rt))),
                                            mkU32(0x7fff))),
                                mkU8(0xff),
                                unop(Iop_16HIto8,
                                     unop(Iop_32to16,
                                          binop(Iop_Shl32,
                                                getIReg(rt),
                                                mkU8(1))))));
         assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32to16,
                                                      getIReg(rt))),
                                           mkU32(0x00008000)),
                                     mkU32(0x0)),
                               mkexpr(t10),
                               mkU8(0x0)));
         assign(t11, binop(Iop_CmpEQ32,
                           binop(Iop_And32,
                                 unop(Iop_16Uto32,
                                      unop(Iop_32to16,
                                           getIReg(rt))),
                                 mkU32(0x00008000)),
                           mkU32(0x0)));
         assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
                                      mkU32(0x7f80),
                                      binop(Iop_And32,
                                            unop(Iop_16Uto32,
                                                 unop(Iop_32to16,
                                                       getIReg(rt))),
                                            mkU32(0x7fff))),
                                binop(Iop_Or32,
                                      getDSPControl(),
                                      mkU32(0x00400000)),
                                getDSPControl()));
         putDSPControl(IRExpr_ITE(mkexpr(t11),
                                  mkexpr(t12),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00400000))));

         assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
                                      mkU32(0x7f80),
                                      binop(Iop_And32,
                                            unop(Iop_16Uto32,
                                                 unop(Iop_32HIto16,
                                                       getIReg(rt))),
                                            mkU32(0x7fff))),
                                mkU8(0xff),
                                unop(Iop_16HIto8,
                                     unop(Iop_32HIto16,
                                          binop(Iop_Shl32,
                                                getIReg(rt),
                                                mkU8(1))))));
         assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           unop(Iop_16Uto32,
                                                unop(Iop_32HIto16,
                                                      getIReg(rt))),
                                           mkU32(0x00008000)),
                                     mkU32(0x0)),
                               mkexpr(t13),
                               mkU8(0x0)));
         assign(t14, binop(Iop_CmpEQ32,
                           binop(Iop_And32,
                                 unop(Iop_16Uto32,
                                      unop(Iop_32HIto16,
                                           getIReg(rt))),
                                 mkU32(0x00008000)),
                           mkU32(0x0)));
         assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
                                      mkU32(0x7f80),
                                      binop(Iop_And32,
                                            unop(Iop_16Uto32,
                                                 unop(Iop_32HIto16,
                                                       getIReg(rt))),
                                            mkU32(0x7fff))),
                                binop(Iop_Or32,
                                      getDSPControl(),
                                      mkU32(0x00400000)),
                                getDSPControl()));
         putDSPControl(IRExpr_ITE(mkexpr(t14),
                                  mkexpr(t15),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00400000))));

         putIReg(rd, binop(Iop_16HLto32,
                           binop(Iop_8HLto16,
                                 mkexpr(t1), mkexpr(t0)),
                           binop(Iop_8HLto16,
                                 mkexpr(t3), mkexpr(t2))));
         break;
      }

      case 0x14: {  /* PRECRQ.PH.W */
         DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt);
         vassert(!mode64);
         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32HIto16, getIReg(rs)),
                           unop(Iop_32HIto16, getIReg(rt))));
         break;
      }

      case 0x15: {  /* PRECRQ_RS.PH.W */
         DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I64);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);

         assign(t0, binop(Iop_Add64,
                          binop(Iop_32HLto64,
                                binop(Iop_Shr32,
                                      binop(Iop_And32,
                                            getIReg(rs),
                                            mkU32(0x80000000)),
                                      mkU8(31)),
                                getIReg(rs)),
                          mkU64(0x0000000000008000ULL)));
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t0)),
                                mkU32(0x1)),
                          binop(Iop_And32,
                                binop(Iop_Shr32,
                                      unop(Iop_64to32, mkexpr(t0)),
                                      mkU8(31)),
                                mkU32(0x1))));
         assign(t2, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x7fffffff),
                               unop(Iop_64to32, mkexpr(t0))));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  getDSPControl()));
         assign(t3, binop(Iop_Add64,
                          binop(Iop_32HLto64,
                                binop(Iop_Shr32,
                                      binop(Iop_And32,
                                            getIReg(rt),
                                            mkU32(0x80000000)),
                                      mkU8(31)),
                                getIReg(rt)),
                          mkU64(0x0000000000008000ULL)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t3)),
                                mkU32(0x1)),
                          binop(Iop_And32,
                                binop(Iop_Shr32,
                                      unop(Iop_64to32, mkexpr(t3)),
                                      mkU8(31)),
                                mkU32(0x1))));
         assign(t5, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x7fffffff),
                               unop(Iop_64to32, mkexpr(t3))));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  getDSPControl()));
         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32HIto16, mkexpr(t2)),
                           unop(Iop_32HIto16, mkexpr(t5))));
         break;
      }

      case 0x1E: {  /* PRECR_SRA.PH.W */
         DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd);
         vassert(!mode64);

         if (0 == rd) {
            putIReg(rt, binop(Iop_16HLto32,
                              unop(Iop_32to16, getIReg(rt)),
                              unop(Iop_32to16, getIReg(rs))));
         } else {
            putIReg(rt, binop(Iop_16HLto32,
                              unop(Iop_32to16, binop(Iop_Sar32,
                                    getIReg(rt),
                                    mkU8(rd))),
                              unop(Iop_32to16, binop(Iop_Sar32,
                                    getIReg(rs),
                                    mkU8(rd)))));
         }

         break;
      }

      case 0x1F: {  /* PRECR_SRA_R.PH.W */
         DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);

         if (0 == rd) {
            putIReg(rt, binop(Iop_16HLto32,
                              unop(Iop_32to16, getIReg(rt)),
                              unop(Iop_32to16, getIReg(rs))));
         } else {
            assign(t0, binop(Iop_Shr32,
                             binop(Iop_Add32,
                                   binop(Iop_Sar32,
                                         getIReg(rt),
                                         mkU8(rd - 1)),
                                   mkU32(0x1)),
                             mkU8(0x1)));
            assign(t1, binop(Iop_Shr32,
                             binop(Iop_Add32,
                                   binop(Iop_Sar32,
                                         getIReg(rs),
                                         mkU8(rd - 1)),
                                   mkU32(0x1)),
                             mkU8(0x1)));
            putIReg(rt, binop(Iop_16HLto32,
                              unop(Iop_32to16, mkexpr(t0)),
                              unop(Iop_32to16, mkexpr(t1))));
         };

         break;
      }

      case 0xE: {  /* PACKRL.PH */
         DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, getIReg(rs)),
                           unop(Iop_32HIto16, getIReg(rt))));
         break;
      }

      case 0x18: {  /* CMPGDU.EQ.QB */
         DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1,
                binop(Iop_CmpEQ32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpEQ32,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      case 0x19: {  /* CMPGDU.LT.QB */
         DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpLT32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      case 0x1A: {  /* CMPGDU.LE.QB */
         DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         assign(t1, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               mkU32(0x00000001),
                               mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x01000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfeffffff))));

         assign(t2, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16, getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32to16,
                                         getIReg(rt))))));
         assign(t6, IRExpr_ITE(mkexpr(t2),
                               mkU32(0x00000002), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x02000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfdffffff))));

         assign(t3, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16to8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t7, IRExpr_ITE(mkexpr(t3),
                               mkU32(0x00000004), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x04000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xfbffffff))));

         assign(t4, binop(Iop_CmpLE32U,
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rs)))),
                          unop(Iop_8Uto32,
                               unop(Iop_16HIto8,
                                    unop(Iop_32HIto16,
                                         getIReg(rt))))));
         assign(t8, IRExpr_ITE(mkexpr(t4),
                               mkU32(0x00000008), mkU32(0)));
         putDSPControl(IRExpr_ITE(mkexpr(t4),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x08000000)),
                                  binop(Iop_And32,
                                        getDSPControl(),
                                        mkU32(0xf7ffffff))));

         putIReg(rd, binop(Iop_Or32,
                           binop(Iop_Or32,
                                 binop(Iop_Or32,
                                       mkexpr(t5), mkexpr(t6)),
                                 mkexpr(t7)),
                           mkexpr(t8)));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_SHLL_QB( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
              t15, t16, t17;
   UInt   rs, rt, rd, sa;


   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x0: {  /* SHLL.QB */
         DIP("shll.qb r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I1);
         t10 = newTemp(Ity_I1);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            /* Shift bits 7..0 and 23..16. */
            assign(t0, binop(Iop_Shl32,
                             binop(Iop_And32,
                                   getIReg(rt),
                                   mkU32(0x00ff00ff)),
                             mkU8(rs)));
            assign(t1, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t0),
                                   mkU32(0xff000000)),
                             mkU32(0x00000000)));
            assign(t2, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t0),
                                   mkU32(0xff000000)),
                             mkU32(0xff000000)));
            assign(t7, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t0),
                                   mkU32(0x0000ff00)),
                             mkU32(0x00000000)));
            assign(t8, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t0),
                                   mkU32(0x0000ff00)),
                             mkU32(0x000ff00)));
            /* Shift bits 15..8 and 31..24. */
            assign(t3, binop(Iop_Shl32,
                             binop(Iop_Shr32,
                                   binop(Iop_And32,
                                         getIReg(rt),
                                         mkU32(0xff00ff00)),
                                   mkU8(8)),
                             mkU8(rs)));
            assign(t4, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t3),
                                   mkU32(0xff000000)),
                             mkU32(0x00000000)));
            assign(t5, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t3),
                                   mkU32(0xff000000)),
                             mkU32(0xff000000)));
            assign(t9, binop(Iop_CmpNE32,
                             binop(Iop_And32,
                                   mkexpr(t3),
                                   mkU32(0x0000ff00)),
                             mkU32(0x00000000)));
            assign(t10, binop(Iop_CmpNE32,
                              binop(Iop_And32,
                                    mkexpr(t3),
                                    mkU32(0x0000ff00)),
                              mkU32(0x0000ff00)));

            assign(t6, binop(Iop_Or32,
                             binop(Iop_Or32,
                                   binop(Iop_And32,
                                         unop(Iop_1Uto32,
                                              mkexpr(t1)),
                                         unop(Iop_1Uto32,
                                              mkexpr(t2))),
                                   binop(Iop_And32,
                                         unop(Iop_1Uto32,
                                              mkexpr(t7)),
                                         unop(Iop_1Uto32,
                                              mkexpr(t8)))),
                             binop(Iop_Or32,
                                   binop(Iop_And32,
                                         unop(Iop_1Uto32,
                                              mkexpr(t4)),
                                         unop(Iop_1Uto32,
                                              mkexpr(t5))),
                                   binop(Iop_And32,
                                         unop(Iop_1Uto32,
                                              mkexpr(t9)),
                                         unop(Iop_1Uto32,
                                              mkexpr(t10))))));

            putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                           mkexpr(t6),
                                           mkU32(0x0)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putIReg(rd, binop(Iop_Or32,
                              binop(Iop_Shl32,
                                    binop(Iop_And32,
                                          mkexpr(t3),
                                          mkU32(0x00ff00ff)),
                                    mkU8(8)),
                              binop(Iop_And32,
                                    mkexpr(t0),
                                    mkU32(0x00ff00ff))));
         }

         break;
      }

      case 0x3: {  /* SHRL.QB */
         DIP("shrl.qb r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I8);
         t9 = newTemp(Ity_I32);

         assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
         assign(t0, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t1, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               mkexpr(t0),
                               unop(Iop_32to8, mkexpr(t9)))));

         assign(t2, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t3, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               mkexpr(t2),
                               unop(Iop_32to8, mkexpr(t9)))));

         assign(t4, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t5, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               mkexpr(t4),
                               unop(Iop_32to8, mkexpr(t9)))));

         assign(t6, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t7, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               mkexpr(t6),
                               unop(Iop_32to8, mkexpr(t9)))));
         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      mkexpr(t9),
                                      mkU32(0x0)),
                                getIReg(rt),
                                binop(Iop_16HLto32,
                                      binop(Iop_8HLto16,
                                            mkexpr(t7),
                                            mkexpr(t5)),
                                      binop(Iop_8HLto16,
                                            mkexpr(t3),
                                            mkexpr(t1)))));
         break;
      }

      case 0x2: {  /* SHLLV.QB */
         DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I1);
         t10 = newTemp(Ity_I1);
         t11 = newTemp(Ity_I8);

         assign(t11, unop(Iop_32to8,
                          binop(Iop_And32,
                                getIReg(rs),
                                mkU32(0x7))));
         /* Shift bits 7..0 and 23..16. */
         assign(t0, binop(Iop_Shl32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x00ff00ff)),
                          mkexpr(t11)));
         assign(t1, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0xff000000)),
                          mkU32(0x00000000)));
         assign(t2, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0xff000000)),
                          mkU32(0xff000000)));
         assign(t7, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x0000ff00)),
                          mkU32(0x00000000)));
         assign(t8, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t0),
                                mkU32(0x0000ff00)),
                          mkU32(0x000ff00)));
         /* Shift bits 15..8 and 31..24. */
         assign(t3, binop(Iop_Shl32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0xff00ff00)),
                                mkU8(8)),
                          mkexpr(t11)));
         assign(t4, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t3),
                                mkU32(0xff000000)),
                          mkU32(0x00000000)));
         assign(t5, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t3),
                                mkU32(0xff000000)),
                          mkU32(0xff000000)));
         assign(t9, binop(Iop_CmpNE32,
                          binop(Iop_And32,
                                mkexpr(t3),
                                mkU32(0x0000ff00)),
                          mkU32(0x00000000)));
         assign(t10, binop(Iop_CmpNE32,
                           binop(Iop_And32,
                                 mkexpr(t3),
                                 mkU32(0x0000ff00)),
                           mkU32(0x0000ff00)));

         assign(t6, binop(Iop_Or32,
                          binop(Iop_Or32,
                                binop(Iop_And32,
                                      unop(Iop_1Uto32,
                                           mkexpr(t1)),
                                      unop(Iop_1Uto32,
                                           mkexpr(t2))),
                                binop(Iop_And32,
                                      unop(Iop_1Uto32,
                                           mkexpr(t7)),
                                      unop(Iop_1Uto32,
                                           mkexpr(t8)))),
                          binop(Iop_Or32,
                                binop(Iop_And32,
                                      unop(Iop_1Uto32,
                                           mkexpr(t4)),
                                      unop(Iop_1Uto32,
                                           mkexpr(t5))),
                                binop(Iop_And32,
                                      unop(Iop_1Uto32,
                                           mkexpr(t9)),
                                      unop(Iop_1Uto32,
                                           mkexpr(t10))))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t6),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  getDSPControl()));
         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      unop(Iop_8Uto32, mkexpr(t11)),
                                      mkU32(0)),
                                getIReg(rt),
                                binop(Iop_Or32,
                                      binop(Iop_Shl32,
                                            binop(Iop_And32,
                                                  mkexpr(t3),
                                                  mkU32(0xff00ff)),
                                            mkU8(8)),
                                      binop(Iop_And32,
                                            mkexpr(t0),
                                            mkU32(0x00ff00ff)))));
         break;
      }

      case 0x1: {  /* SHRLV.QB */
         DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I8);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I8);

         assign(t0, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               unop(Iop_8Uto32,
                                    unop(Iop_32to8, getIReg(rt))),
                               mkU8(rs))));
         assign(t1, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               unop(Iop_8Uto32,
                                    unop(Iop_16HIto8,
                                         unop(Iop_32to16,
                                              getIReg(rt)))),
                               mkU8(rs))));
         assign(t2, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               unop(Iop_8Uto32,
                                    unop(Iop_16to8,
                                         unop(Iop_32HIto16,
                                              getIReg(rt)))),
                               mkU8(rs))));
         assign(t3, unop(Iop_32to8,
                         binop(Iop_Shr32,
                               unop(Iop_8Uto32,
                                    unop(Iop_16HIto8,
                                         unop(Iop_32HIto16,
                                              getIReg(rt)))),
                               mkU8(rs))));
         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
                       binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
         break;
      }

      case 0x4: {  /* SHRA.QB */
         DIP("shra.qb r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I32);

         /* ========== GPR[rt]_31..24 ========== */
         assign(t1,
                unop(Iop_8Uto32,
                     unop(Iop_16HIto8,
                          unop(Iop_32HIto16, getIReg(rt)))));
         assign(t2,
                binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
         /* tempD_7..0 */
         assign(t0,
                binop(Iop_Or32,
                      mkexpr(t2),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t1),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));

         /* ========== GPR[rt]_23..16 ========== */
         assign(t4,
                unop(Iop_8Uto32,
                     unop(Iop_16to8,
                          unop(Iop_32HIto16, getIReg(rt)))));
         assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
         /* tempC_7..0 */
         assign(t3,
                binop(Iop_Or32,
                      mkexpr(t5),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t4),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));

         /* ========== GPR[rt]_15..8 ========== */
         assign(t7,
                unop(Iop_8Uto32,
                     unop(Iop_16HIto8,
                          unop(Iop_32to16, getIReg(rt)))));
         assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
         /* tempB_7..0 */
         assign(t6,
                binop(Iop_Or32,
                      mkexpr(t8),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t7),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));

         /* ========== GPR[rt]_7..0 ========== */
         assign(t10,
                unop(Iop_8Uto32,
                     unop(Iop_16to8,
                          unop(Iop_32to16, getIReg(rt)))));
         assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
         /* tempB_7..0 */
         assign(t9,
                binop(Iop_Or32,
                      mkexpr(t11),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t10),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));

         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16,
                             unop(Iop_32to8, mkexpr(t0)),
                             unop(Iop_32to8, mkexpr(t3))),
                       binop(Iop_8HLto16,
                             unop(Iop_32to8, mkexpr(t6)),
                             unop(Iop_32to8, mkexpr(t9)))));
         break;
      }

      case 0x5: {  /* SHRA_R.QB */
         DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I8);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            assign(t0, unop(Iop_8Sto32,
                            unop(Iop_16to8,
                                 unop(Iop_32to16, getIReg(rt)))));
            assign(t1, unop(Iop_32to8,
                            binop(Iop_Sar32,
                                  binop(Iop_Add32,
                                        mkexpr(t0),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(rs - 1))),
                                  mkU8(rs))));

            assign(t2, unop(Iop_8Sto32,
                            unop(Iop_16HIto8,
                                 unop(Iop_32to16, getIReg(rt)))));
            assign(t3, unop(Iop_32to8,
                            binop(Iop_Sar32,
                                  binop(Iop_Add32,
                                        mkexpr(t2),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(rs - 1))),
                                  mkU8(rs))));

            assign(t4, unop(Iop_8Sto32,
                            unop(Iop_16to8,
                                 unop(Iop_32HIto16, getIReg(rt)))));
            assign(t5, unop(Iop_32to8,
                            binop(Iop_Sar32,
                                  binop(Iop_Add32,
                                        mkexpr(t4),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(rs - 1))),
                                  mkU8(rs))));

            assign(t6, unop(Iop_8Sto32,
                            unop(Iop_16HIto8,
                                 unop(Iop_32HIto16, getIReg(rt)))));
            assign(t7, unop(Iop_32to8,
                            binop(Iop_Sar32,
                                  binop(Iop_Add32,
                                        mkexpr(t6),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(rs - 1))),
                                  mkU8(rs))));
            putIReg(rd, binop(Iop_16HLto32,
                              binop(Iop_8HLto16,
                                    mkexpr(t7), mkexpr(t5)),
                              binop(Iop_8HLto16,
                                    mkexpr(t3), mkexpr(t1))));
         }

         break;
      }

      case 0x6: {  /* SHRAV.QB */
         DIP("shrav.qb r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);

         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);

         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);

         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I32);

         /* ========== GPR[rt]_31..24 ========== */
         assign(t1,
                unop(Iop_8Uto32,
                     unop(Iop_16HIto8,
                          unop(Iop_32HIto16, getIReg(rt)))));
         assign(t2,
                binop(Iop_Shr32,
                      mkexpr(t1),
                      unop(Iop_32to8, binop(Iop_And32,
                                            getIReg(rs),
                                            mkU32(0x7)))));
         /* tempD_7..0 */
         assign(t0,
                binop(Iop_Or32,
                      mkexpr(t2),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t1),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8,
                                  mkU8(0x8),
                                  unop(Iop_32to8, binop(Iop_And32,
                                        getIReg(rs),
                                        mkU32(0x7)))
                                 ))));

         /* ========== GPR[rt]_23..16 ========== */
         assign(t4,
                unop(Iop_8Uto32,
                     unop(Iop_16to8,
                          unop(Iop_32HIto16, getIReg(rt)))));
         assign(t5,
                binop(Iop_Shr32,
                      mkexpr(t4),
                      unop(Iop_32to8, binop(Iop_And32,
                                            getIReg(rs),
                                            mkU32(0x7)))));
         /* tempC_7..0 */
         assign(t3,
                binop(Iop_Or32,
                      mkexpr(t5),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t4),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8,
                                  mkU8(0x8),
                                  unop(Iop_32to8, binop(Iop_And32,
                                        getIReg(rs),
                                        mkU32(0x7)))
                                 ))));

         /* ========== GPR[rt]_15..8 ========== */
         assign(t7,
                unop(Iop_8Uto32,
                     unop(Iop_16HIto8,
                          unop(Iop_32to16, getIReg(rt)))));
         assign(t8,
                binop(Iop_Shr32,
                      mkexpr(t7),
                      unop(Iop_32to8, binop(Iop_And32,
                                            getIReg(rs),
                                            mkU32(0x7)))));
         /* tempB_7..0 */
         assign(t6,
                binop(Iop_Or32,
                      mkexpr(t8),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t7),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8,
                                  mkU8(0x8),
                                  unop(Iop_32to8, binop(Iop_And32,
                                        getIReg(rs),
                                        mkU32(0x7)))
                                 ))));

         /* ========== GPR[rt]_7..0 ========== */
         assign(t10,
                unop(Iop_8Uto32,
                     unop(Iop_16to8,
                          unop(Iop_32to16, getIReg(rt)))));
         assign(t11,
                binop(Iop_Shr32,
                      mkexpr(t10),
                      unop(Iop_32to8, binop(Iop_And32,
                                            getIReg(rs),
                                            mkU32(0x7)))));
         /* tempB_7..0 */
         assign(t9,
                binop(Iop_Or32,
                      mkexpr(t11),
                      binop(Iop_Shl32,
                            IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkexpr(t10),
                                                   mkU32(0x00000080)
                                                  ),
                                             mkU32(0x00000080)),
                                       mkU32(0xFFFFFFFF),
                                       mkU32(0x00000000)),
                            binop(Iop_Sub8,
                                  mkU8(0x8),
                                  unop(Iop_32to8, binop(Iop_And32,
                                        getIReg(rs),
                                        mkU32(0x7)))
                                 ))));

         putIReg(rd,
                 binop(Iop_16HLto32,
                       binop(Iop_8HLto16,
                             unop(Iop_32to8,
                                  IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkU32(rs),
                                                   mkU32(0x7)
                                                  ),
                                             mkU32(0x0)),
                                             mkexpr(t1),
                                             mkexpr(t0))),
                             unop(Iop_32to8,
                                  IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkU32(rs),
                                                   mkU32(0x7)
                                                  ),
                                             mkU32(0x0)),
                                             mkexpr(t2),
                                             mkexpr(t3)))),
                       binop(Iop_8HLto16,
                             unop(Iop_32to8,
                                  IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkU32(rs),
                                                   mkU32(0x7)
                                                  ),
                                             mkU32(0x0)),
                                             mkexpr(t5),
                                             mkexpr(t6))),
                             unop(Iop_32to8,
                                  IRExpr_ITE(binop(Iop_CmpEQ32,
                                             binop(Iop_And32,
                                                   mkU32(rs),
                                                   mkU32(0x7)
                                                  ),
                                             mkU32(0x0)),
                                             mkexpr(t8),
                                             mkexpr(t9))))));
         break;
      }

      case 0x7: {  /* SHRAV_R.QB */
         DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I8);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I8);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I8);
         t8 = newTemp(Ity_I8);
         t9 = newTemp(Ity_I32);

         assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
         assign(t8, unop(Iop_32to8,
                         binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
         assign(t0, unop(Iop_8Sto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t1, unop(Iop_32to8,
                         binop(Iop_Sar32,
                               binop(Iop_Add32,
                                     mkexpr(t0),
                                     binop(Iop_Shl32,
                                           mkU32(0x1),
                                           mkexpr(t8))),
                               unop(Iop_32to8,
                                    mkexpr(t9)))));

         assign(t2, unop(Iop_8Sto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t3, unop(Iop_32to8,
                         binop(Iop_Sar32,
                               binop(Iop_Add32,
                                     mkexpr(t2),
                                     binop(Iop_Shl32,
                                           mkU32(0x1),
                                           mkexpr(t8))),
                               unop(Iop_32to8, mkexpr(t9)))));

         assign(t4, unop(Iop_8Sto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t5, unop(Iop_32to8,
                         binop(Iop_Sar32,
                               binop(Iop_Add32,
                                     mkexpr(t4),
                                     binop(Iop_Shl32,
                                           mkU32(0x1),
                                           mkexpr(t8))),
                               unop(Iop_32to8, mkexpr(t9)))));

         assign(t6, unop(Iop_8Sto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t7, unop(Iop_32to8,
                         binop(Iop_Sar32,
                               binop(Iop_Add32,
                                     mkexpr(t6),
                                     binop(Iop_Shl32,
                                           mkU32(0x1),
                                           mkexpr(t8))),
                               unop(Iop_32to8, mkexpr(t9)))));
         putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      mkexpr(t9),
                                      mkU32(0x0)),
                                getIReg(rt),
                                binop(Iop_16HLto32,
                                      binop(Iop_8HLto16,
                                            mkexpr(t7),
                                            mkexpr(t5)),
                                      binop(Iop_8HLto16,
                                            mkexpr(t3),
                                            mkexpr(t1)))));
         break;
      }

      case 0x8: {  /* SHLL.PH */
         DIP("shll.ph r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            /* Shift lower 16 bits. */
            assign(t0, binop(Iop_Shl32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32to16, getIReg(rt))),
                             mkU8(rs)));

            assign(t1, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t0),
                                        mkU8(16)),
                                  mkU32(0))));
            assign(t2, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t0),
                                        mkU8(16)),
                                  mkU32(0xffffffff))));
            assign(t3, binop(Iop_And32,
                             mkexpr(t1),
                             mkexpr(t2)));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t3),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           binop(Iop_And32,
                                                 getIReg(rt),
                                                 mkU32(0x00008000)),
                                           binop(Iop_And32,
                                                 mkexpr(t0),
                                                 mkU32(0x00008000))
                                          ),
                                     getDSPControl(),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000))));
            /* Shift higher 16 bits. */
            assign(t4, binop(Iop_Shl32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32HIto16, getIReg(rt))),
                             mkU8(rs)));

            assign(t5, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t4),
                                        mkU8(16)),
                                  mkU32(0))));
            assign(t6, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t4),
                                        mkU8(16)),
                                  mkU32(0xffffffff))));
            assign(t7, binop(Iop_And32,
                             mkexpr(t5),
                             mkexpr(t6)));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t7),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t7),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           binop(Iop_And32,
                                                 getIReg(rt),
                                                 mkU32(0x80000000)),
                                           binop(Iop_Shl32,
                                                 binop(Iop_And32,
                                                       mkexpr(t4),
                                                       mkU32(0x00008000)),
                                                 mkU8(16))
                                          ),
                                     getDSPControl(),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000))));
            putIReg(rd, binop(Iop_16HLto32,
                              unop(Iop_32to16, mkexpr(t4)),
                              unop(Iop_32to16, mkexpr(t0))));
         }

         break;
      }

      case 0x9: {  /* SHRA.PH */
         DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            assign(t0, binop(Iop_Sar32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32to16, getIReg(rt))),
                             mkU8(rs)));
            assign(t1, binop(Iop_Sar32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32HIto16, getIReg(rt))),
                             mkU8(rs)));
            putIReg(rd, binop(Iop_16HLto32,
                              unop(Iop_32to16, mkexpr(t1)),
                              unop(Iop_32to16, mkexpr(t0))));
         }

         break;
      }

      case 0xA: {  /* SHLLV.PH */
         DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I32);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);

         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));

         /* Shift lower 16 bits. */
         assign(t2, binop(Iop_Shl32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));

         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x00000000)));
         assign(t4, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0xffffffff)));
         assign(t10, binop(Iop_And32,
                           unop(Iop_1Sto32, mkexpr(t3)),
                           unop(Iop_1Sto32, mkexpr(t4))));
         assign(t5, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x00008000)),
                          mkU8(15)));
         assign(t12, binop(Iop_CmpEQ32,
                           mkexpr(t5),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       mkexpr(t2),
                                       mkU32(0x00008000)),
                                 mkU8(15))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t10),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  IRExpr_ITE(mkexpr(t12),
                                             getDSPControl(),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x400000)))
                                 ));
         /* Shift higher 16 bits. */
         assign(t6, binop(Iop_Shl32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));

         assign(t7, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t6))),
                          mkU32(0x00000000)));
         assign(t8, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t6))),
                          mkU32(0xffffffff)));
         assign(t11, binop(Iop_And32,
                           unop(Iop_1Sto32, mkexpr(t7)),
                           unop(Iop_1Sto32, mkexpr(t8))));

         assign(t9, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x80000000)),
                          mkU8(31)));
         assign(t13, binop(Iop_CmpEQ32,
                           mkexpr(t9),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       mkexpr(t6),
                                       mkU32(0x00008000)),
                                 mkU8(15))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t11),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  IRExpr_ITE(mkexpr(t13),
                                             getDSPControl(),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x400000)))
                                 ));

         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t6)),
                           unop(Iop_32to16, mkexpr(t2))));
         break;
      }

      case 0xB: {  /* SHRAV.PH */
         DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);

         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
         assign(t2, binop(Iop_Sar32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));
         assign(t3, binop(Iop_Sar32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));
         putIReg(rd,
                 binop(Iop_16HLto32,
                       IRExpr_ITE(mkexpr(t1),
                                  unop(Iop_32HIto16, getIReg(rt)),
                                  unop(Iop_32to16, mkexpr(t3))),
                       IRExpr_ITE(mkexpr(t1),
                                  unop(Iop_32to16, getIReg(rt)),
                                  unop(Iop_32to16, mkexpr(t2)))));
         break;
      }

      case 0xC: {  /* SHLL_S.PH */
         DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I32);
         t12 = newTemp(Ity_I32);
         t13 = newTemp(Ity_I32);
         t14 = newTemp(Ity_I32);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            /* Shift lower 16 bits. */
            assign(t0, binop(Iop_Shl32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32to16, getIReg(rt))),
                             mkU8(rs)));

            assign(t1, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t0),
                                        mkU8(16)),
                                  mkU32(0))));
            assign(t2, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t0),
                                        mkU8(16)),
                                  mkU32(0xffffffff))));
            assign(t3, binop(Iop_And32,
                             mkexpr(t1),
                             mkexpr(t2)));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t3),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           binop(Iop_And32,
                                                 getIReg(rt),
                                                 mkU32(0x00008000)),
                                           binop(Iop_And32,
                                                 mkexpr(t0),
                                                 mkU32(0x00008000))
                                          ),
                                     getDSPControl(),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000))));
            assign(t8,
                   IRExpr_ITE(binop(Iop_CmpEQ32,
                                    mkexpr(t3),
                                    mkU32(0x1)),
                              IRExpr_ITE(binop(Iop_CmpEQ32,
                                               binop(Iop_And32,
                                                     getIReg(rt),
                                                     mkU32(0x8000)),
                                               mkU32(0)),
                                         mkU32(0x00007fff),
                                         mkU32(0x00008000)),
                              binop(Iop_And32,
                                    mkexpr(t0),
                                    mkU32(0x0000ffff))));
            assign(t10,
                   IRExpr_ITE(binop(Iop_CmpEQ32,
                                    binop(Iop_And32,
                                          getIReg(rt),
                                          mkU32(0x00008000)),
                                    binop(Iop_And32,
                                          mkexpr(t0),
                                          mkU32(0x00008000))),
                              mkexpr(t8),
                              IRExpr_ITE(binop(Iop_CmpEQ32,
                                               binop(Iop_And32,
                                                     getIReg(rt),
                                                     mkU32(0x8000)),
                                               mkU32(0)),
                                         mkU32(0x00007fff),
                                         mkU32(0x00008000))));
            /* Shift higher 16 bits. */
            assign(t4, binop(Iop_Shl32,
                             unop(Iop_16Sto32,
                                  unop(Iop_32HIto16, getIReg(rt))),
                             mkU8(rs)));

            assign(t5, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t4),
                                        mkU8(16)),
                                  mkU32(0))));
            assign(t6, unop(Iop_1Uto32,
                            binop(Iop_CmpNE32,
                                  binop(Iop_Sar32,
                                        mkexpr(t4),
                                        mkU8(16)),
                                  mkU32(0xffffffff))));
            assign(t7, binop(Iop_And32,
                             mkexpr(t5),
                             mkexpr(t6)));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t7),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           mkexpr(t7),
                                           mkU32(0x1)),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000)),
                                     getDSPControl()));
            assign(t12, binop(Iop_Shl32,
                              binop(Iop_And32,
                                    mkexpr(t4),
                                    mkU32(0x8000)),
                              mkU8(16)));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           binop(Iop_And32,
                                                 getIReg(rt),
                                                 mkU32(0x80000000)),
                                           mkexpr(t12)),
                                     getDSPControl(),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000))));
            assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
                                         binop(Iop_And32,
                                               getIReg(rt),
                                               mkU32(0x80000000)),
                                         mkU32(0)),
                                   mkU32(0x7fff0000),
                                   mkU32(0x80000000)));
            assign(t9,
                   IRExpr_ITE(binop(Iop_CmpEQ32,
                                    mkexpr(t7),
                                    mkU32(0x1)),
                              mkexpr(t13),
                              binop(Iop_Shl32,
                                    binop(Iop_And32,
                                          mkexpr(t4),
                                          mkU32(0x0000ffff)),
                                    mkU8(16))));
            assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
                                         binop(Iop_And32,
                                               getIReg(rt),
                                               mkU32(0x80000000)),
                                         mkU32(0)),
                                   mkU32(0x7fff0000),
                                   mkU32(0x80000000)));
            assign(t11,
                   IRExpr_ITE(binop(Iop_CmpEQ32,
                                    binop(Iop_And32,
                                          getIReg(rt),
                                          mkU32(0x80000000)),
                                    binop(Iop_Shl32,
                                          binop(Iop_And32,
                                                mkexpr(t4),
                                                mkU32(0x00008000)),
                                          mkU8(16))),
                              mkexpr(t9),
                              mkexpr(t14)));
            putIReg(rd, binop(Iop_Or32,
                              mkexpr(t10),
                              mkexpr(t11)));
         }

         break;
      }

      case 0xD: {  /* SHRA_R.PH */
         DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            assign(t0, binop(Iop_Sar32,
                             binop(Iop_Add32,
                                   unop(Iop_16Sto32,
                                        unop(Iop_32to16,
                                             getIReg(rt))),
                                   binop(Iop_Shl32,
                                         mkU32(0x1),
                                         mkU8(rs - 1))),
                             mkU8(rs)));
            assign(t1, binop(Iop_Sar32,
                             binop(Iop_Add32,
                                   unop(Iop_16Sto32,
                                        unop(Iop_32HIto16,
                                             getIReg(rt))),
                                   binop(Iop_Shl32,
                                         mkU32(0x1),
                                         mkU8(rs - 1))),
                             mkU8(rs)));
            putIReg(rd, binop(Iop_16HLto32,
                              unop(Iop_32to16, mkexpr(t1)),
                              unop(Iop_32to16, mkexpr(t0))));
         }

         break;
      }

      case 0xE: {  /* SHLLV_S.PH */
         DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I32);
         t12 = newTemp(Ity_I1);
         t13 = newTemp(Ity_I1);
         t14 = newTemp(Ity_I16);
         t15 = newTemp(Ity_I16);
         t16 = newTemp(Ity_I16);
         t17 = newTemp(Ity_I16);

         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));

         /* Shift lower 16 bits. */
         assign(t2, binop(Iop_Shl32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));

         assign(t3, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0x00000000)));
         assign(t4, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t2))),
                          mkU32(0xffffffff)));
         assign(t10, binop(Iop_And32,
                           unop(Iop_1Sto32, mkexpr(t3)),
                           unop(Iop_1Sto32, mkexpr(t4))));
         assign(t5, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x00008000)),
                          mkU8(15)));
         assign(t12, binop(Iop_CmpEQ32,
                           mkexpr(t5),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       mkexpr(t2),
                                       mkU32(0x00008000)),
                                 mkU8(15))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t10),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  IRExpr_ITE(mkexpr(t12),
                                             getDSPControl(),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x400000)))
                                 ));
         assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t5),
                                      mkU32(0x0)),
                                mkU16(0x8000),
                                mkU16(0x7fff)));
         assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t10),
                                      mkU32(0x0)),
                                mkexpr(t14),
                                IRExpr_ITE(mkexpr(t12),
                                           unop(Iop_32to16,
                                                mkexpr(t2)),
                                           mkexpr(t14))));
         /* Shift higher 16 bits. */
         assign(t6, binop(Iop_Shl32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));

         assign(t7, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t6))),
                          mkU32(0x00000000)));
         assign(t8, binop(Iop_CmpNE32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, mkexpr(t6))),
                          mkU32(0xffffffff)));
         assign(t11, binop(Iop_And32,
                           unop(Iop_1Sto32, mkexpr(t7)),
                           unop(Iop_1Sto32, mkexpr(t8))));

         assign(t9, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x80000000)),
                          mkU8(31)));
         assign(t13, binop(Iop_CmpEQ32,
                           mkexpr(t9),
                           binop(Iop_Shr32,
                                 binop(Iop_And32,
                                       mkexpr(t6),
                                       mkU32(0x00008000)),
                                 mkU8(15))));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t11),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  IRExpr_ITE(mkexpr(t13),
                                             getDSPControl(),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x400000)))
                                 ));

         assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t9),
                                      mkU32(0x0)),
                                mkU16(0x8000),
                                mkU16(0x7fff)));
         assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
                                      mkexpr(t11),
                                      mkU32(0x0)),
                                mkexpr(t16),
                                IRExpr_ITE(mkexpr(t13),
                                           unop(Iop_32to16,
                                                mkexpr(t6)),
                                           mkexpr(t16))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
         break;
      }

      case 0xF: {  /* SHRAV_R.PH */
         DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);

         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
         assign(t2, unop(Iop_32to8,
                         binop(Iop_Sub32, mkexpr(t0), mkU32(1))));

         assign(t3, binop(Iop_Sar32,
                          binop(Iop_Add32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16, getIReg(rt))),
                                binop(Iop_Shl32,
                                      mkU32(0x1),
                                      mkexpr(t2))),
                          unop(Iop_32to8, mkexpr(t0))));
         assign(t4, binop(Iop_Sar32,
                          binop(Iop_Add32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rt))),
                                binop(Iop_Shl32,
                                      mkU32(0x1),
                                      mkexpr(t2))),
                          unop(Iop_32to8, mkexpr(t0))));

         putIReg(rd, binop(Iop_16HLto32,
                           IRExpr_ITE(mkexpr(t1),
                                      unop(Iop_32HIto16,
                                           getIReg(rt)),
                                      unop(Iop_32to16,
                                           mkexpr(t4))),
                           IRExpr_ITE(mkexpr(t1),
                                      unop(Iop_32to16, getIReg(rt)),
                                      unop(Iop_32to16,
                                           mkexpr(t3)))));
         break;
      }

      case 0x14: {  /* SHLL_S.W */
         DIP("shll_s.w r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            /* t0-bits that will be discarded, sign extended to
               32bits. */
            assign(t0, binop(Iop_Sar32,
                             binop(Iop_And32,
                                   getIReg(rt),
                                   binop(Iop_Sar32,
                                         mkU32(0x80000000),
                                         mkU8(rs - 1))),
                             mkU8(32 - rs)));

            assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
                                        binop(Iop_And32,
                                              getIReg(rt),
                                              mkU32(0x80000000)),
                                        mkU32(0x0)),
                                  mkU32(0x7fffffff),
                                  mkU32(0x80000000)));

            assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
            assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
                                        binop(Iop_And32,
                                              getIReg(rt),
                                              mkU32(0x80000000)),
                                        binop(Iop_And32,
                                              mkexpr(t2),
                                              mkU32(0x80000000))),
                                  mkexpr(t2),
                                  mkexpr(t1)));

            assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t0),
                                        mkU32(0x0)),
                                  IRExpr_ITE(binop(Iop_CmpNE32,
                                                   mkexpr(t0),
                                                   mkU32(0xffffffff)
                                                  ),
                                             mkexpr(t1),
                                             mkexpr(t3)),
                                  mkexpr(t3)));
            assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t0),
                                        mkU32(0xffffffff)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                           mkexpr(t0),
                                           mkU32(0x0)),
                                     mkexpr(t5),
                                     getDSPControl()));
            putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                           binop(Iop_And32,
                                                 getIReg(rt),
                                                 mkU32(0x80000000)),
                                           binop(Iop_And32,
                                                 mkexpr(t2),
                                                 mkU32(0x80000000))
                                          ),
                                     getDSPControl(),
                                     binop(Iop_Or32,
                                           getDSPControl(),
                                           mkU32(0x400000))));
            putIReg(rd, mkexpr(t4));
         }

         break;
      }

      case 0x15: {  /* SHRA_R.W */
         DIP("shra_r.w r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);

         if (0 == rs) {
            putIReg(rd, getIReg(rt));
         } else {
            putIReg(rd, binop(Iop_Add32,
                              binop(Iop_Sar32,
                                    getIReg(rt), mkU8(rs)),
                              binop(Iop_Shr32,
                                    binop(Iop_And32,
                                          getIReg(rt),
                                          binop(Iop_Shl32,
                                                mkU32(0x1),
                                                mkU8(rs - 1))),
                                    mkU8(rs - 1))));
         }

         break;
      }

      case 0x16: {  /* SHLLV_S.W */
         DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I64);
         t4 = newTemp(Ity_I1);
         t5 = newTemp(Ity_I1);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I32);

         /* Check if shift amount is zero. */
         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));

         /* t2 = sign of the input value. */
         assign(t2, binop(Iop_Shr32,
                          binop(Iop_And32,
                                getIReg(rt),
                                mkU32(0x80000000)),
                          mkU8(31)));
         /* Shift left input value and check for overflow. */
         assign(t3, binop(Iop_Shl64,
                          unop(Iop_32Sto64, getIReg(rt)),
                          unop(Iop_32to8, mkexpr(t0))));
         assign(t4, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32, mkexpr(t3)),
                          mkU32(0x00000000)));
         assign(t5, binop(Iop_CmpNE32,
                          unop(Iop_64HIto32, mkexpr(t3)),
                          mkU32(0xffffffff)));
         assign(t6, binop(Iop_And32,
                          unop(Iop_1Uto32, mkexpr(t4)),
                          unop(Iop_1Uto32, mkexpr(t5))));
         assign(t7, binop(Iop_CmpEQ32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      getIReg(rt),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t3)),
                                      mkU32(0x80000000)),
                                mkU8(31))));

         putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x400000)),
                                  IRExpr_ITE(mkexpr(t7),
                                             getDSPControl(),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x400000)))
                                 ));

         assign(t8, IRExpr_ITE(unop(Iop_32to1,
                                    mkexpr(t2)),
                               mkU32(0x80000000),
                               mkU32(0x7fffffff)));
         putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
                                IRExpr_ITE(unop(Iop_32to1,
                                                mkexpr(t2)),
                                           mkU32(0x80000000),
                                           mkU32(0x7fffffff)),
                                IRExpr_ITE(mkexpr(t7),
                                           unop(Iop_64to32,
                                                mkexpr(t3)),
                                           mkexpr(t8))));
         break;
      }

      case 0x17: {  /* SHRAV_R.W */
         DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I8);

         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
         assign(t2, unop(Iop_32to8,
                         binop(Iop_Sub32, mkexpr(t0), mkU32(1))));

         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                getIReg(rt),
                                binop(Iop_Sar32,
                                      binop(Iop_Add32,
                                            binop(Iop_Sar32,
                                                  getIReg(rt),
                                                  mkexpr(t2)),
                                            mkU32(0x1)),
                                      mkU8(1))));
         break;
      }

      case 0x19: {  /* SHRL.PH */
         DIP("shrl.ph r%u, r%u, %u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         assign(t0, binop(Iop_Shr32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU8(rs)));
         assign(t1, binop(Iop_Shr32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU8(rs)));
         putIReg(rd, binop(Iop_16HLto32,
                           unop(Iop_32to16, mkexpr(t1)),
                           unop(Iop_32to16, mkexpr(t0))));
         break;
      }

      case 0x1B: {  /* SHRLV.PH */
         DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I16);
         t5 = newTemp(Ity_I16);

         /* Get shift amount from lower 5 bits of rs
            and check if it is zero. */
         assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
         assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));

         assign(t2, binop(Iop_Shr32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));
         assign(t3, binop(Iop_Shr32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          unop(Iop_32to8, mkexpr(t0))));

         assign(t4, IRExpr_ITE(mkexpr(t1),
                               unop(Iop_32HIto16, getIReg(rt)),
                               unop(Iop_32to16, mkexpr(t3))));
         assign(t5, IRExpr_ITE(mkexpr(t1),
                               unop(Iop_32to16, getIReg(rt)),
                               unop(Iop_32to16, mkexpr(t2))));
         putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_ADDUH_QB( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
   UInt   rs, rt, rd, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x00: {  /* ADDUH.QB */
         DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);

         assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));

         putIReg(rd, mkexpr(t0));
         break;
      }

      case 0x1: {  /* SUBUH.QB */
         DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);

         assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));

         putIReg(rd, mkexpr(t0));
         break;
      }

      case 0x02: {  /* ADDUH_R.QB */
         DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I8);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I8);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I8);
         t9 = newTemp(Ity_I32);
         t10 = newTemp(Ity_I32);
         t11 = newTemp(Ity_I8);

         /* Extract input bytes, add values, add 1 and half the
            result. */
         assign(t0, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rs)))));
         assign(t1, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t2, unop(Iop_16to8,
                         unop(Iop_32to16,
                              binop(Iop_Shr32,
                                    binop(Iop_Add32,
                                          binop(Iop_Add32,
                                                mkexpr(t0),
                                                mkexpr(t1)),
                                          mkU32(0x00000001)),
                                    mkU8(0x01)))));

         assign(t3, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rs)))));
         assign(t4, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t5, unop(Iop_16to8,
                         unop(Iop_32to16,
                              binop(Iop_Shr32,
                                    binop(Iop_Add32,
                                          binop(Iop_Add32,
                                                mkexpr(t3),
                                                mkexpr(t4)),
                                          mkU32(0x00000001)),
                                    mkU8(0x01)))));

         assign(t6, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rs)))));
         assign(t7, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t8, unop(Iop_16to8,
                         unop(Iop_32to16,
                              binop(Iop_Shr32,
                                    binop(Iop_Add32,
                                          binop(Iop_Add32,
                                                mkexpr(t7),
                                                mkexpr(t6)),
                                          mkU32(0x00000001)),
                                    mkU8(0x01)))));

         assign(t9, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32HIto16, getIReg(rs)))));
         assign(t10, unop(Iop_8Uto32,
                          unop(Iop_16HIto8,
                               unop(Iop_32HIto16, getIReg(rt)))));
         assign(t11, unop(Iop_16to8,
                          unop(Iop_32to16,
                               binop(Iop_Shr32,
                                     binop(Iop_Add32,
                                           binop(Iop_Add32,
                                                 mkexpr(t9),
                                                 mkexpr(t10)),
                                           mkU32(0x00000001)),
                                     mkU8(0x01)))));

         putIReg(rd, binop(Iop_16HLto32,
                           binop(Iop_8HLto16,
                                 mkexpr(t11), mkexpr(t8)),
                           binop(Iop_8HLto16,
                                 mkexpr(t5), mkexpr(t2))));
         break;
      }

      case 0x3: {  /* SUBUH_R.QB */
         DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I32);
         t7 = newTemp(Ity_I32);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I8);
         t10 = newTemp(Ity_I8);
         t11 = newTemp(Ity_I8);
         t12 = newTemp(Ity_I8);

         /* Extract each byte of rs and rt. */
         assign(t1, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rs)))));
         assign(t2, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rs)))));
         assign(t3, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rs)))));
         assign(t4, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32HIto16, getIReg(rs)))));

         assign(t5, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t6, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32to16, getIReg(rt)))));
         assign(t7, unop(Iop_8Uto32,
                         unop(Iop_16to8,
                              unop(Iop_32HIto16, getIReg(rt)))));
         assign(t8, unop(Iop_8Uto32,
                         unop(Iop_16HIto8,
                              unop(Iop_32HIto16, getIReg(rt)))));

         /* Add 1 to each resulting byte and half the results. */
         assign(t9, unop(Iop_16to8,
                         unop(Iop_32to16,
                              binop(Iop_Shr32,
                                    binop(Iop_Add32,
                                          binop(Iop_Sub32,
                                                mkexpr(t1),
                                                mkexpr(t5)),
                                          mkU32(0x00000001)),
                                    mkU8(0x01)))));
         assign(t10, unop(Iop_16to8,
                          unop(Iop_32to16,
                               binop(Iop_Shr32,
                                     binop(Iop_Add32,
                                           binop(Iop_Sub32,
                                                 mkexpr(t2),
                                                 mkexpr(t6)),
                                           mkU32(0x00000001)),
                                     mkU8(0x01)))));
         assign(t11, unop(Iop_16to8,
                          unop(Iop_32to16,
                               binop(Iop_Shr32,
                                     binop(Iop_Add32,
                                           binop(Iop_Sub32,
                                                 mkexpr(t3),
                                                 mkexpr(t7)),
                                           mkU32(0x00000001)),
                                     mkU8(0x01)))));
         assign(t12, unop(Iop_16to8,
                          unop(Iop_32to16,
                               binop(Iop_Shr32,
                                     binop(Iop_Add32,
                                           binop(Iop_Sub32,
                                                 mkexpr(t4),
                                                 mkexpr(t8)),
                                           mkU32(0x00000001)),
                                     mkU8(0x01)))));

         putIReg(rd, binop(Iop_16HLto32,
                           binop(Iop_8HLto16,
                                 mkexpr(t12), mkexpr(t11)),
                           binop(Iop_8HLto16,
                                 mkexpr(t10), mkexpr(t9))));
         break;
      }

      case 0x8: {  /* ADDQH.PH */
         DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I16);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I16);

         /* Add lower halfs of rs and rt
            and right shift the result by 1. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));
         assign(t1, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     mkexpr(t0),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));
         /* Add higher halfs of rs and rt
            and right shift the result by 1. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));
         assign(t3, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     mkexpr(t2),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));
         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
         break;
      }

      case 0x9: {  /* SUBQH.PH */
         DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);

         putIReg(rd, binop(Iop_HSub16Sx2,
                           getIReg(rs), getIReg(rt)));
         break;
      }

      case 0xA: {/* ADDQH_R.PH */
         DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I16);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I16);

         /* Add lower halfs of rs and rt, add 1
            and right shift the result by 1. */
         assign(t0, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));
         assign(t1, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     binop(Iop_Add32,
                                           mkexpr(t0),
                                           mkU32(0x1)),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));
         /* Add higher halfs of rs and rt, add 1
            and right shift the result by 1. */
         assign(t2, binop(Iop_Add32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));
         assign(t3, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     binop(Iop_Add32,
                                           mkexpr(t2),
                                           mkU32(0x1)),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
         break;
      }

      case 0xB: {  /* SUBQH_R.PH */
         DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I16);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I16);

         /* Sub lower halfs of rs and rt, add 1
            and right shift the result by 1. */
         assign(t0, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));
         assign(t1, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     binop(Iop_Add32,
                                           mkexpr(t0),
                                           mkU32(0x1)),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));
         /* Sub higher halfs of rs and rt, add 1
            and right shift the result by 1. */
         assign(t2, binop(Iop_Sub32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt)))));
         assign(t3, unop(Iop_32to16,
                         binop(Iop_Shr32,
                               binop(Iop_And32,
                                     binop(Iop_Add32,
                                           mkexpr(t2),
                                           mkU32(0x1)),
                                     mkU32(0x0001fffe)),
                               mkU8(0x1))));

         putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
         break;
      }

      case 0xC: {  /* MUL.PH */
         DIP("mul.ph r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);

         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_16Sto32,
                           unop(Iop_32HIto16, getIReg(rs))),
                      unop(Iop_16Sto32,
                           unop(Iop_32HIto16, getIReg(rt)))));
         /* DSP Control flag. */
         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
                                       binop(Iop_CmpLE32S,
                                             mkexpr(t0),
                                             mkU32(0x7FFF))),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00200000)),
                                  IRExpr_ITE(binop(Iop_CmpLT32S,
                                             mkexpr(t0),
                                             mkU32(0xFFFF8000)
                                                  ),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl())));

         assign(t1,
                binop(Iop_Mul32,
                      unop(Iop_16Sto32,
                           unop(Iop_32to16, getIReg(rs))),
                      unop(Iop_16Sto32,
                           unop(Iop_32to16, getIReg(rt)))));
         /* DSP Control flag. */
         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
                                       binop(Iop_CmpLE32S,
                                             mkexpr(t1),
                                             mkU32(0x7FFF))),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00200000)),
                                  IRExpr_ITE(binop(Iop_CmpLT32S,
                                             mkexpr(t1),
                                             mkU32(0xFFFF8000)
                                                  ),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl())));

         assign(t2, binop(Iop_16HLto32,
                          unop(Iop_32to16, mkexpr(t0)),
                          unop(Iop_32to16, mkexpr(t1))));
         putIReg(rd, mkexpr(t2));
         break;
      }

      case 0xE: {  /* MUL_S.PH */
         DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);

         /* t0 - signed intermediate result. */
         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_16Sto32,
                           unop(Iop_32HIto16, getIReg(rs))),
                      unop(Iop_16Sto32,
                           unop(Iop_32HIto16, getIReg(rt)))));

         assign(t1,
                IRExpr_ITE(unop(Iop_Not1,
                                binop(Iop_CmpLE32S,
                                      mkexpr(t0),
                                      mkU32(0x7FFF))),
                           mkU32(0x00007FFF),
                           IRExpr_ITE(binop(Iop_CmpLT32S,
                                            mkexpr(t0),
                                            mkU32(0xFFFF8000)),
                                      mkU32(0xFFFF8000),
                                      mkexpr(t0))));

         /* DSP Control flag. */
         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
                                       binop(Iop_CmpLE32S,
                                             mkexpr(t0),
                                             mkU32(0x7FFF))),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00200000)),
                                  IRExpr_ITE(binop(Iop_CmpLT32S,
                                             mkexpr(t0),
                                             mkU32(0xFFFF8000)
                                                  ),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl())));

         /* t2 - signed intermediate result. */
         assign(t2, binop(Iop_Mul32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt)))));

         assign(t3, IRExpr_ITE(unop(Iop_Not1,
                                    binop(Iop_CmpLE32S,
                                          mkexpr(t2),
                                          mkU32(0x7FFF))),
                               mkU32(0x00007FFF),
                               IRExpr_ITE(binop(Iop_CmpLT32S,
                                                mkexpr(t2),
                                                mkU32(0xFFFF8000)),
                                          mkU32(0xFFFF8000),
                                          mkexpr(t2))));

         /* DSP Control flag. */
         putDSPControl(IRExpr_ITE(unop(Iop_Not1,
                                       binop(Iop_CmpLE32S,
                                             mkexpr(t2),
                                             mkU32(0x7FFF))),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        mkU32(0x00200000)),
                                  IRExpr_ITE(binop(Iop_CmpLT32S,
                                             mkexpr(t2),
                                             mkU32(0xFFFF8000)
                                                  ),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl())));

         assign(t4, binop(Iop_16HLto32,
                          unop(Iop_32to16, mkexpr(t1)),
                          unop(Iop_32to16, mkexpr(t3))));
         putIReg(rd, mkexpr(t4));
         break;
      }

      case 0x10: {  /* ADDQH.W */
         DIP("addqh.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);

         assign(t0, binop(Iop_Add64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));
         assign(t1, binop(Iop_And64,
                          mkexpr(t0),
                          mkU64(0x00000001fffffffeULL)));
         putIReg(rd, unop(Iop_64to32,
                          binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
         break;
      }

      case 0x11: {  /* SUBQH.W */
         DIP("subqh.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);

         assign(t0, binop(Iop_Sub64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));
         assign(t1, binop(Iop_And64,
                          mkexpr(t0),
                          mkU64(0x00000001fffffffeULL)));
         putIReg(rd, unop(Iop_64to32,
                          binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
         break;
      }

      case 0x12: {  /* ADDQH_R.W */
         DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0, binop(Iop_Add64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));
         assign(t1, binop(Iop_Add64,
                          mkexpr(t0),
                          mkU64(0x0000000000000001ULL)));
         assign(t2, binop(Iop_And64,
                          mkexpr(t1),
                          mkU64(0x00000001fffffffeULL)));
         putIReg(rd, unop(Iop_64to32,
                          binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
         break;
      }

      case 0x13: {  /* SUBQH_R.W */
         DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0, binop(Iop_Sub64,
                          unop(Iop_32Sto64, getIReg(rs)),
                          unop(Iop_32Sto64, getIReg(rt))));
         assign(t1, binop(Iop_Add64,
                          mkexpr(t0),
                          mkU64(0x0000000000000001ULL)));
         assign(t2, binop(Iop_And64,
                          mkexpr(t1),
                          mkU64(0x00000001fffffffeULL)));
         putIReg(rd, unop(Iop_64to32,
                          binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
         break;
      }

      case 0x16: {  /* MULQ_S.W */
         DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t0, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                getIReg(rt), getIReg(rs)),
                          mkU8(0x1)));
         assign(t1, binop(Iop_CmpEQ32,
                          getIReg(rt), mkU32(0x80000000)));
         assign(t2, binop(Iop_CmpEQ32,
                          getIReg(rs), mkU32(0x80000000)));

         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  IRExpr_ITE(mkexpr(t2),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(mkexpr(t2),
                                           mkU32(0x7fffffff),
                                           unop(Iop_64HIto32,
                                                mkexpr(t0))),
                                unop(Iop_64HIto32, mkexpr(t0))));
         break;
      }

      case 0x17: {  /* MULQ_RS.W */
         DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I1);
         t2 = newTemp(Ity_I1);

         assign(t0, binop(Iop_Add64,
                          binop(Iop_Shl64,
                                binop(Iop_MullS32,
                                      getIReg(rt),
                                      getIReg(rs)),
                                mkU8(0x1)),
                          mkU64(0x0000000080000000ULL)));
         assign(t1,
                binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
         assign(t2,
                binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
         putDSPControl(IRExpr_ITE(mkexpr(t1),
                                  IRExpr_ITE(mkexpr(t2),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   mkU32(0x00200000)
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         putIReg(rd, IRExpr_ITE(mkexpr(t1),
                                IRExpr_ITE(mkexpr(t2),
                                           mkU32(0x7fffffff),
                                           unop(Iop_64HIto32,
                                                mkexpr(t0))),
                                unop(Iop_64HIto32, mkexpr(t0))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_DPAW_PH( UInt cins )
{
   IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10;
   UInt   rs, rt, sa, ac;

   rs = get_rs(cins);
   rt = get_rt(cins);
   sa = get_sa(cins);
   ac = get_acNo(cins);

   switch (sa) {
      case 0x0: {  /* DPA.W.PH */
         DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t1,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t2,
                binop(Iop_Add64,
                      getAcc(ac),
                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
         putAcc(ac, mkexpr(t2));
         break;
      }

      case 0x1: {  /* DPS.W.PH */
         DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t1,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t2,
                binop(Iop_Sub64,
                      getAcc(ac),
                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
         putAcc(ac, mkexpr(t2));
         break;
      }

      case 0x2: {  /* MULSA.W.PH */
         DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);

         assign(t4, getAcc(ac));
         assign(t0, binop(Iop_Mul32,
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rt))),
                          unop(Iop_16Sto32,
                               unop(Iop_32to16, getIReg(rs)))));
         assign(t1, binop(Iop_Mul32,
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          unop(Iop_16Sto32,
                               unop(Iop_32HIto16, getIReg(rs)))));
         assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
         putAcc(ac, binop(Iop_Add64,
                          mkexpr(t4),
                          unop(Iop_32Sto64, mkexpr(t2))));
         break;
      }

      case 0x3: {  /* DPAU.H.QBL */
         DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t1,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t2,
                unop(Iop_32Uto64,
                     binop(Iop_Add32,
                           mkexpr(t0),
                           mkexpr(t1))));
         assign(t3,
                binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0x4: {  /* DPAQ_S.W.PH */
         DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16, getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16, getIReg(rt)))
                               ),
                          mkU8(0x1)));
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t8,
                IRExpr_ITE(mkexpr(t6),
                           IRExpr_ITE(mkexpr(t7),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t5)),
                           mkexpr(t5)));

         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  IRExpr_ITE(mkexpr(t7),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t9, binop(Iop_Add64,
                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
                          mkexpr(t0)));
         putAcc(ac, mkexpr(t9));
         break;
      }

      case 0x5: {  /* DPSQ_S.W.PH */
         DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5,
                binop(Iop_Shl64,
                      binop(Iop_MullS32,
                            unop(Iop_16Sto32,
                                 unop(Iop_32to16, getIReg(rs))),
                            unop(Iop_16Sto32,
                                 unop(Iop_32to16, getIReg(rt)))),
                      mkU8(0x1)));
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t8,
                IRExpr_ITE(mkexpr(t6),
                           IRExpr_ITE(mkexpr(t7),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t5)),
                           mkexpr(t5)));

         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  IRExpr_ITE(mkexpr(t7),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t9,
                binop(Iop_Sub64,
                      mkexpr(t0),
                      binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
         putAcc(ac, mkexpr(t9));
         break;
      }

      case 0x6: {  /* MULSAQ_S.W.PH */
         DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I32);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I64);
         t8 = newTemp(Ity_I32);
         t9 = newTemp(Ity_I32);

         assign(t0, unop(Iop_16Sto32,
                         unop(Iop_32HIto16, getIReg(rs))));
         assign(t1, unop(Iop_16Sto32,
                         unop(Iop_32HIto16, getIReg(rt))));

         assign(t8, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     unop(Iop_16Uto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rs))),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     unop(Iop_16Uto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rt))),
                                     mkU32(0x8000)))));
         /* DSPControl_outflag:16+acc <- 1 */
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t8),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x00010000),
                                              mkU8(ac))),
                                  getDSPControl()));

         /* tempB_31..0 */
         assign(t2,
                IRExpr_ITE(binop(Iop_CmpNE32,
                                 mkexpr(t8), mkU32(0x0)),
                           mkU32(0x7FFFFFFF),
                           binop(Iop_Shl32,
                                 binop(Iop_Mul32,
                                       mkexpr(t0), mkexpr(t1)),
                                 mkU8(1))));

         assign(t3, unop(Iop_16Sto32,
                         unop(Iop_32to16, getIReg(rs))));
         assign(t4, unop(Iop_16Sto32,
                         unop(Iop_32to16, getIReg(rt))));

         assign(t9, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     unop(Iop_16Uto32,
                                          unop(Iop_32to16,
                                               getIReg(rs))),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     unop(Iop_16Uto32,
                                          unop(Iop_32to16,
                                               getIReg(rt))),
                                     mkU32(0x8000)))));
         /* DSPControl_outflag:16+acc <- 1 */
         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        mkexpr(t9),
                                        mkU32(0x0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x00010000),
                                              mkU8(ac))),
                                  getDSPControl()));
         /* tempA_31..0 */
         assign(t5,
                IRExpr_ITE(binop(Iop_CmpNE32,
                                 mkexpr(t9),
                                 mkU32(0x0)),
                           mkU32(0x7FFFFFFF),
                           binop(Iop_Shl32,
                                 binop(Iop_Mul32,
                                       mkexpr(t3),
                                       mkexpr(t4)),
                                 mkU8(1))));
         /* dotp_63..0 */
         assign(t6,
                binop(Iop_Sub64,
                      unop(Iop_32Sto64, mkexpr(t2)),
                      unop(Iop_32Sto64, mkexpr(t5))));
         /* tempC_63..0 */
         assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));

         putAcc(ac, mkexpr(t7));
         break;
      }

      case 0x7: {  /* DPAU.H.QBR */
         DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t1,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t2, unop(Iop_32Uto64,
                         binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
         assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0x8: {  /* DPAX.W.PH */
         DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t1,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t2,
                binop(Iop_Add64,
                      getAcc(ac),
                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
         putAcc(ac, mkexpr(t2));
         break;
      }

      case 0x9: {  /* DPSX.W.PH */
         DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I64);

         assign(t0,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t1,
                unop(Iop_32Sto64,
                     binop(Iop_Mul32,
                           unop(Iop_16Sto32,
                                unop(Iop_32to16, getIReg(rs))),
                           unop(Iop_16Sto32,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t2,
                binop(Iop_Sub64,
                      getAcc(ac),
                      binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
         putAcc(ac, mkexpr(t2));
         break;
      }

      case 0xB: {  /* DPSU.H.QBL */
         DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t1,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32HIto16, getIReg(rt))))));
         assign(t2,
                unop(Iop_32Uto64,
                     binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
         assign(t3,
                binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
         putAcc(ac, mkexpr(t3));
         break;
      }

      case 0xC: {  /* DPAQ_SA.L.W */
         DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I64);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I1);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                getIReg(rs), getIReg(rt)),
                          mkU8(0x1)));

         assign(t2, binop(Iop_CmpEQ32,
                          getIReg(rs),
                          mkU32(0x80000000)));
         assign(t3, binop(Iop_CmpEQ32,
                          getIReg(rt),
                          mkU32(0x80000000)));

         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x7fffffffffffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5, binop(Iop_Add64,
                          unop(Iop_32Uto64,
                               unop(Iop_64to32, mkexpr(t0))),
                          unop(Iop_32Uto64,
                               unop(Iop_64to32, mkexpr(t4)))));
         assign(t6,
                binop(Iop_Add64,
                      binop(Iop_Add64,
                            unop(Iop_32Sto64,
                                 unop(Iop_64HIto32, mkexpr(t0))),
                            unop(Iop_32Sto64,
                                 unop(Iop_64HIto32, mkexpr(t4)))),
                      unop(Iop_32Uto64,
                           binop(Iop_And32,
                                 unop(Iop_64HIto32, mkexpr(t5)),
                                 mkU32(0x1)))));
         assign(t7, binop(Iop_32HLto64,
                          unop(Iop_64to32, mkexpr(t6)),
                          unop(Iop_64to32, mkexpr(t5))));
         assign(t8, binop(Iop_CmpEQ32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t6)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t6)),
                                mkU32(0x00000001))));
         assign(t9, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                unop(Iop_64HIto32,
                                     mkexpr(t6)),
                                mkU32(0x00000001)),
                          mkU32(0x1)));
         putDSPControl(IRExpr_ITE(mkexpr(t8),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         putAcc(ac,
                IRExpr_ITE(mkexpr(t8),
                           mkexpr(t7),
                           IRExpr_ITE(mkexpr(t9),
                                      mkU64(0x8000000000000000ULL),
                                      mkU64(0x7fffffffffffffffULL)))
               );
         break;
      }

      case 0xD: {  /* DPSQ_SA.L.W */
         DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I64);
         t7 = newTemp(Ity_I64);
         t8 = newTemp(Ity_I1);
         t9 = newTemp(Ity_I1);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                getIReg(rs), getIReg(rt)),
                          mkU8(0x1)));

         assign(t2, binop(Iop_CmpEQ32,
                          getIReg(rs),
                          mkU32(0x80000000)));
         assign(t3, binop(Iop_CmpEQ32,
                          getIReg(rt),
                          mkU32(0x80000000)));

         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x7fffffffffffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5, binop(Iop_Sub64,
                          unop(Iop_32Uto64,
                               unop(Iop_64to32, mkexpr(t0))),
                          unop(Iop_32Uto64,
                               unop(Iop_64to32, mkexpr(t4)))));
         assign(t6, binop(Iop_Sub64,
                          binop(Iop_Add64,
                                unop(Iop_32Sto64,
                                     unop(Iop_64HIto32, mkexpr(t0))
                                    ),
                                unop(Iop_32Sto64,
                                     unop(Iop_1Sto32,
                                          binop(Iop_CmpLT32U,
                                                unop(Iop_64to32,
                                                      mkexpr(t0)),
                                                unop(Iop_64to32,
                                                      mkexpr(t4)))))),
                          unop(Iop_32Sto64,
                               unop(Iop_64HIto32, mkexpr(t4)))));
         assign(t7, binop(Iop_32HLto64,
                          unop(Iop_64to32, mkexpr(t6)),
                          unop(Iop_64to32, mkexpr(t5))));
         assign(t8, binop(Iop_CmpEQ32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t6)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t6)),
                                mkU32(0x00000001))));
         assign(t9, binop(Iop_CmpEQ32,
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t6)),
                                mkU32(0x00000001)),
                          mkU32(0x1)));
         putDSPControl(IRExpr_ITE(mkexpr(t8),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         putAcc(ac,
                IRExpr_ITE(mkexpr(t8),
                           mkexpr(t7),
                           IRExpr_ITE(mkexpr(t9),
                                      mkU64(0x8000000000000000ULL),
                                      mkU64(0x7fffffffffffffffULL)))
               );
         break;
      }

      case 0xF: {  /* DPSU.H.QBR */
         DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt);
         vassert(!mode64);

         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I64);
         t3 = newTemp(Ity_I64);

         assign(t0,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16HIto8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t1,
                binop(Iop_Mul32,
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rs)))),
                      unop(Iop_8Uto32,
                           unop(Iop_16to8,
                                unop(Iop_32to16, getIReg(rt))))));
         assign(t2, unop(Iop_32Uto64,
                         binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
         assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
         putAcc(ac, mkexpr(t3));

         break;
      }

      case 0x10: {  /* MAQ_SA.W.PHL */
         DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));
         assign(t1, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl register.
         */
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         /* Add intermediate product and value in the
            accumulator. */
         assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));

         /* Compare bits 31 and 32 of the value in t5. */
         assign(t6, binop(Iop_CmpEQ32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t5)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t5)),
                                mkU32(1))));
         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         assign(t7,
                IRExpr_ITE(mkexpr(t6),
                           mkexpr(t5),
                           IRExpr_ITE(binop(Iop_CmpEQ32,
                                            binop(Iop_And32,
                                                  unop(Iop_64HIto32,
                                                        mkexpr(t5)),
                                                  mkU32(1)),
                                            mkU32(0x0)),
                                      mkU64(0x000000007fffffffULL),
                                      mkU64(0xffffffff80000000ULL)))
               );
         putAcc(ac, mkexpr(t7));
         break;
      }

      case 0x12: {  /* MAQ_SA.W.PHR */
         DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));
         assign(t1, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl
            register. */
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));
         /* Add intermediate product and value in the
            accumulator. */
         assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));

         /* Compare bits 31 and 32 of the value in t5. */
         assign(t6, binop(Iop_CmpEQ32,
                          binop(Iop_Shr32,
                                binop(Iop_And32,
                                      unop(Iop_64to32, mkexpr(t5)),
                                      mkU32(0x80000000)),
                                mkU8(31)),
                          binop(Iop_And32,
                                unop(Iop_64HIto32, mkexpr(t5)),
                                mkU32(1))));
         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         assign(t7,
                IRExpr_ITE(mkexpr(t6),
                           mkexpr(t5),
                           IRExpr_ITE(binop(Iop_CmpEQ32,
                                            binop(Iop_And32,
                                                  unop(Iop_64HIto32,
                                                        mkexpr(t5)),
                                                  mkU32(1)),
                                            mkU32(0x0)),
                                      mkU64(0x000000007fffffffULL),
                                      mkU64(0xffffffff80000000ULL)))
               );
         putAcc(ac, mkexpr(t7));
         break;
      }

      case 0x14: {  /* MAQ_S.W.PHL */
         DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I64);

         assign(t5, getAcc(ac));

         assign(t0, unop(Iop_16Sto32,
                         unop(Iop_32HIto16, getIReg(rs))));
         assign(t1, unop(Iop_16Sto32,
                         unop(Iop_32HIto16, getIReg(rt))));

         assign(t2, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0xffff)),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t1),
                                           mkU32(0xffff)),
                                     mkU32(0x8000)))));

         assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));

         assign(t4, unop(Iop_64to32,
                         binop(Iop_MullS32,
                               mkexpr(t0), mkexpr(t1))));
         putAcc(ac, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Add64,
                                     unop(Iop_32Sto64,
                                          binop(Iop_Shl32,
                                                mkexpr(t4),
                                                mkU8(0x1))),
                                     mkexpr(t5)),
                               binop(Iop_Add64,
                                     mkexpr(t5),
                                     unop(Iop_32Sto64,
                                          mkU32(0x7fffffff)))));
         break;
      }

      case 0x16: {  /* MAQ_S.W.PHR */
         DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I32);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I32);
         t5 = newTemp(Ity_I64);

         assign(t5, getAcc(ac));

         assign(t0, unop(Iop_16Sto32,
                         unop(Iop_32to16, getIReg(rs))));
         assign(t1, unop(Iop_16Sto32,
                         unop(Iop_32to16, getIReg(rt))));

         assign(t2, binop(Iop_And32,
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t0),
                                           mkU32(0xffff)),
                                     mkU32(0x8000))),
                          unop(Iop_1Sto32,
                               binop(Iop_CmpEQ32,
                                     binop(Iop_And32,
                                           mkexpr(t1),
                                           mkU32(0xffff)),
                                     mkU32(0x8000)))));

         assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));

         putDSPControl(IRExpr_ITE(mkexpr(t3),
                                  getDSPControl(),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));

         assign(t4, unop(Iop_64to32,
                         binop(Iop_MullS32,
                               mkexpr(t0), mkexpr(t1))));
         putAcc(ac, IRExpr_ITE(mkexpr(t3),
                               binop(Iop_Add64,
                                     unop(Iop_32Sto64,
                                          binop(Iop_Shl32,
                                                mkexpr(t4),
                                                mkU8(0x1))),
                                     mkexpr(t5)),
                               binop(Iop_Add64,
                                     mkexpr(t5),
                                     unop(Iop_32Sto64,
                                          mkU32(0x7fffffff)))));
         break;
      }

      case 0x18: {  /* DPAQX_S.W.PH */
         DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16))),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t8,
                IRExpr_ITE(mkexpr(t6),
                           IRExpr_ITE(mkexpr(t7),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t5)),
                           mkexpr(t5)));

         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  IRExpr_ITE(mkexpr(t7),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t9, binop(Iop_Add64,
                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
                          mkexpr(t0)));
         putAcc(ac, mkexpr(t9));
         break;
      }

      case 0x19: {  /* DPSQX_S.W.PH */
         DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);

         assign(t0, getAcc(ac));

         assign(t1, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t4,
                IRExpr_ITE(mkexpr(t2),
                           IRExpr_ITE(mkexpr(t3),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t1)),
                           mkexpr(t1)));

         putDSPControl(IRExpr_ITE(mkexpr(t2),
                                  IRExpr_ITE(mkexpr(t3),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t5, binop(Iop_Shl64,
                          binop(Iop_MullS32,
                                unop(Iop_16Sto32,
                                     unop(Iop_32to16,
                                          getIReg(rs))),
                                unop(Iop_16Sto32,
                                     unop(Iop_32HIto16,
                                          getIReg(rt)))),
                          mkU8(0x1)));
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));
         assign(t8,
                IRExpr_ITE(mkexpr(t6),
                           IRExpr_ITE(mkexpr(t7),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t5)),
                           mkexpr(t5)));

         putDSPControl(IRExpr_ITE(mkexpr(t6),
                                  IRExpr_ITE(mkexpr(t7),
                                             binop(Iop_Or32,
                                                   getDSPControl(),
                                                   binop(Iop_Shl32,
                                                         mkU32(0x1),
                                                         mkU8(ac + 16)
                                                        )
                                                  ),
                                             getDSPControl()),
                                  getDSPControl()));

         assign(t9, binop(Iop_Sub64,
                          mkexpr(t0),
                          binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
         putAcc(ac, mkexpr(t9));
         break;
      }

      case 0x1A: {  /* DPAQX_SA.W.PH */
         DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));
         /* Calculate the first cross dot product and saturate if
            needed. */
         assign(t1, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl
            register. */
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           unop(Iop_1Sto32,
                                                mkexpr(t2)),
                                           unop(Iop_1Sto32,
                                                mkexpr(t3))),
                                     mkU32(0)),
                               mkU64(0x000000007fffffffULL),
                               mkexpr(t1)));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        binop(Iop_And32,
                                              unop(Iop_1Sto32,
                                                    mkexpr(t2)),
                                              unop(Iop_1Sto32,
                                                    mkexpr(t3))),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16))),
                                  getDSPControl()));
         /* Calculate second cross dot product and saturate if
            needed. */
         assign(t5, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl
            register. */
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           unop(Iop_1Sto32,
                                                mkexpr(t6)),
                                           unop(Iop_1Sto32,
                                                mkexpr(t7))),
                                     mkU32(0)),
                               mkU64(0x000000007fffffffULL),
                               mkexpr(t5)));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        binop(Iop_And32,
                                              unop(Iop_1Sto32,
                                                    mkexpr(t6)),
                                              unop(Iop_1Sto32,
                                                    mkexpr(t7))),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16))),
                                  getDSPControl()));
         /* Subtract intermediate products from value in the
            accumulator. */
         assign(t9,
                binop(Iop_Add64,
                      mkexpr(t0),
                      binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));

         putAcc(ac,
                IRExpr_ITE(binop(Iop_CmpEQ32,
                                 binop(Iop_And32,
                                       unop(Iop_64HIto32,
                                            mkexpr(t9)),
                                       mkU32(0x80000000)),
                                 mkU32(0x0)),
                           IRExpr_ITE(binop(Iop_CmpNE32,
                                            unop(Iop_64HIto32,
                                                 binop(Iop_Shl64,
                                                       mkexpr(t9),
                                                       mkU8(1))),
                                            mkU32(0x0)),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t9)),
                           IRExpr_ITE(binop(Iop_CmpNE32,
                                            unop(Iop_64HIto32,
                                                 binop(Iop_Shl64,
                                                       mkexpr(t9),
                                                       mkU8(1))),
                                            mkU32(0xffffffff)),
                                      mkU64(0xffffffff80000000ULL),
                                      mkexpr(t9))));
         assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      unop(Iop_64to32,
                                           mkexpr(t9)),
                                      unop(Iop_64to32,
                                           getAcc(ac))),
                                getDSPControl(),
                                binop(Iop_Or32,
                                      getDSPControl(),
                                      binop(Iop_Shl32,
                                            mkU32(0x1),
                                            mkU8(ac + 16)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        unop(Iop_64HIto32,
                                             mkexpr(t9)),
                                        unop(Iop_64HIto32,
                                             getAcc(ac))),
                                  mkexpr(t10),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         break;
      }

      case 0x1B: {  /* DPSQX_SA.W.PH */
         DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
         vassert(!mode64);
         t0 = newTemp(Ity_I64);
         t1 = newTemp(Ity_I64);
         t2 = newTemp(Ity_I1);
         t3 = newTemp(Ity_I1);
         t4 = newTemp(Ity_I64);
         t5 = newTemp(Ity_I64);
         t6 = newTemp(Ity_I1);
         t7 = newTemp(Ity_I1);
         t8 = newTemp(Ity_I64);
         t9 = newTemp(Ity_I64);
         t10 = newTemp(Ity_I32);

         assign(t0, getAcc(ac));
         /* Calculate the first cross dot product and saturate if
            needed. */
         assign(t1, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl
            register. */
         assign(t2, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t3, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           unop(Iop_1Sto32,
                                                mkexpr(t2)),
                                           unop(Iop_1Sto32,
                                                mkexpr(t3))),
                                     mkU32(0)),
                               mkU64(0x000000007fffffffULL),
                               mkexpr(t1)));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        binop(Iop_And32,
                                              unop(Iop_1Sto32,
                                                    mkexpr(t2)),
                                              unop(Iop_1Sto32,
                                                    mkexpr(t3))),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16))),
                                  getDSPControl()));
         /* Calculate second cross dot product and saturate if
            needed. */
         assign(t5, unop(Iop_32Sto64,
                         binop(Iop_Shl32,
                               binop(Iop_Mul32,
                                     unop(Iop_16Sto32,
                                          unop(Iop_32to16,
                                               getIReg(rs))),
                                     unop(Iop_16Sto32,
                                          unop(Iop_32HIto16,
                                               getIReg(rt)))),
                               mkU8(0x1))));

         /* If both input arguments are equal 0x8000, saturate
            intermediate product and write to DSPControl
            register. */
         assign(t6, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32to16, getIReg(rs))),
                          mkU32(0x00008000)));
         assign(t7, binop(Iop_CmpEQ32,
                          unop(Iop_16Uto32,
                               unop(Iop_32HIto16, getIReg(rt))),
                          mkU32(0x00008000)));

         assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
                                     binop(Iop_And32,
                                           unop(Iop_1Sto32,
                                                mkexpr(t6)),
                                           unop(Iop_1Sto32,
                                                mkexpr(t7))),
                                     mkU32(0)),
                               mkU64(0x000000007fffffffULL),
                               mkexpr(t5)));

         putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
                                        binop(Iop_And32,
                                              unop(Iop_1Sto32,
                                                    mkexpr(t6)),
                                              unop(Iop_1Sto32,
                                                    mkexpr(t7))),
                                        mkU32(0)),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16))),
                                  getDSPControl()));
         /* Subtract intermediate products from value in the
            accumulator. */
         assign(t9,
                binop(Iop_Sub64,
                      mkexpr(t0),
                      binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));

         putAcc(ac,
                IRExpr_ITE(binop(Iop_CmpEQ32,
                                 binop(Iop_And32,
                                       unop(Iop_64HIto32,
                                            mkexpr(t9)),
                                       mkU32(0x80000000)),
                                 mkU32(0x0)),
                           IRExpr_ITE(binop(Iop_CmpNE32,
                                            unop(Iop_64HIto32,
                                                 binop(Iop_Shl64,
                                                       mkexpr(t9),
                                                       mkU8(1))),
                                            mkU32(0x0)),
                                      mkU64(0x000000007fffffffULL),
                                      mkexpr(t9)),
                           IRExpr_ITE(binop(Iop_CmpNE32,
                                            unop(Iop_64HIto32,
                                                 binop(Iop_Shl64,
                                                       mkexpr(t9),
                                                       mkU8(1))),
                                            mkU32(0xffffffff)),
                                      mkU64(0xffffffff80000000ULL),
                                      mkexpr(t9))));
         assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
                                      unop(Iop_64to32,
                                           mkexpr(t9)),
                                      unop(Iop_64to32,
                                           getAcc(ac))),
                                getDSPControl(),
                                binop(Iop_Or32,
                                      getDSPControl(),
                                      binop(Iop_Shl32,
                                            mkU32(0x1),
                                            mkU8(ac + 16)))));
         putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
                                        unop(Iop_64HIto32,
                                             mkexpr(t9)),
                                        unop(Iop_64HIto32,
                                             getAcc(ac))),
                                  mkexpr(t10),
                                  binop(Iop_Or32,
                                        getDSPControl(),
                                        binop(Iop_Shl32,
                                              mkU32(0x1),
                                              mkU8(ac + 16)))));
         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3_APPEND( UInt cins )
{
   IRTemp t1 = 0, t2, t3;
   UInt   rs, rt, rd, sa;

   rs = get_rs(cins);
   rt = get_rt(cins);
   rd = get_rd(cins);
   sa = get_sa(cins);

   switch (sa) {
      case 0x0: {  /* APPEND */
         DIP("append r%u, r%u, %u", rt, rs, rd);
         vassert(!mode64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);

         assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));

         if (31 == rd) {
            putIReg(rt, binop(Iop_Or32,
                              mkexpr(t1),
                              binop(Iop_And32,
                                    getIReg(rs),
                                    mkU32(0x7fffffff))));
         } else if (1 == rd) {
            putIReg(rt,
                    binop(Iop_Or32,
                          mkexpr(t1),
                          binop(Iop_And32,
                                getIReg(rs), mkU32(0x1))));
         } else {
            assign(t2,
                   unop(Iop_Not32,
                        binop(Iop_Shl32,
                              mkU32(0xffffffff), mkU8(rd))));

            putIReg(rt, binop(Iop_Or32,
                              mkexpr(t1),
                              binop(Iop_And32,
                                    getIReg(rs), mkexpr(t2))));
         }

         break;
      }

      case 0x1: {  /* PREPEND */
         DIP("prepend r%u, r%u, %u", rt, rs, rd);
         vassert(!mode64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);

         if (0 != rd) {
            assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));

            if (31 == rd) {
               putIReg(rt, binop(Iop_Or32,
                                 mkexpr(t1),
                                 binop(Iop_Shl32,
                                       binop(Iop_And32,
                                             getIReg(rs),
                                             mkU32(0x7fffffff)),
                                       mkU8(1))));
            } else if (1 == rd) {
               putIReg(rt, binop(Iop_Or32,
                                 mkexpr(t1),
                                 binop(Iop_Shl32,
                                       binop(Iop_And32,
                                             getIReg(rs),
                                             mkU32(0x1)),
                                       mkU8(31))));
            } else {
               assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));

               assign(t3, unop(Iop_Not32,
                               binop(Iop_Shl32,
                                     mkU32(0xffffffff),
                                     unop(Iop_32to8, mkexpr(t2)))));

               putIReg(rt, binop(Iop_Or32,
                                 mkexpr(t1),
                                 binop(Iop_Shl32,
                                       binop(Iop_And32,
                                             getIReg(rs),
                                             mkexpr(t3)),
                                       mkU8(32 - rd))));
            }
         }

         break;
      }

      case 0x10: {  /* BALIGN */
         DIP("balign r%u, r%u, %u", rt, rs, rd);
         vassert(!mode64);
         t1 = newTemp(Ity_I32);
         t2 = newTemp(Ity_I32);
         t3 = newTemp(Ity_I32);

         if ((2 != rd) && (0 != rd)) {
            assign(t1, binop(Iop_Shl32,
                             binop(Iop_And32,
                                   mkU32(rd), mkU32(0x3)),
                             mkU8(0x3)));
            assign(t2, binop(Iop_Shl32,
                             getIReg(rt),
                             unop(Iop_32to8, mkexpr(t1))));
            assign(t3, binop(Iop_Shr32,
                             getIReg(rs),
                             unop(Iop_32to8,
                                  binop(Iop_Shl32,
                                        binop(Iop_Sub32,
                                              mkU32(0x4),
                                              binop(Iop_And32,
                                                    mkU32(rd),
                                                    mkU32(0x3))),
                                        mkU8(0x3)))));
            putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
         }

         break;
      }

      default:
         return -1;
   }

   return 0;
}

static UInt disDSPInstr_MIPS_WRK_Special3( UInt cins )
{
   switch (get_function(cins)) {
      case 0x12: {  /* ABSQ_S.PH */
         return disDSPInstr_MIPS_WRK_Special3_ABSQ_SPH(cins);
      }

      case 0x38: {  /* EXTR.W */
         return disDSPInstr_MIPS_WRK_Special3_EXTR_W(cins);
      }

      case 0xA: {  /* LX */
         return disDSPInstr_MIPS_WRK_Special3_LX(cins);
      }

      case 0xC: {  /* INSV */
         return disDSPInstr_MIPS_WRK_Special3_INSV(cins);
      }

      case 0x10: {  /* ADDU.QB */
         return disDSPInstr_MIPS_WRK_Special3_ADDU_QB(cins);
      }

      case 0x11: {  /* CMPU.EQ.QB */
         return disDSPInstr_MIPS_WRK_Special3_CMPU_EQ_QB(cins);
      }

      case 0x13: {  /* SHLL.QB */
         return disDSPInstr_MIPS_WRK_Special3_SHLL_QB(cins);
      }

      case 0x18: {  /* ADDUH.QB/MUL.PH */
         return disDSPInstr_MIPS_WRK_Special3_ADDUH_QB(cins);
      }

      case 0x30: {  /* DPA.W.PH */
         return disDSPInstr_MIPS_WRK_Special3_DPAW_PH(cins);
      }

      case 0x31: {  /* APPEND */
         return disDSPInstr_MIPS_WRK_Special3_APPEND(cins);
      }

      default:
         return -1;
   }
}

UInt disDSPInstr_MIPS_WRK ( UInt cins )
{
   UInt opcode = get_opcode(cins);

   switch (opcode) {
      case 0x00: {  /* Special */
         return disDSPInstr_MIPS_WRK_Special(cins);
      }

      case 0x1C: {  /* Special2 */
         return disDSPInstr_MIPS_WRK_Special2(cins);
      }

      case 0x1F: {  /* Special3 */
         return disDSPInstr_MIPS_WRK_Special3(cins);
      }

      default:
         return -1;
   }
}
