Home | History | Annotate | Download | only in priv
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- begin                                      guest_mips_toIR.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2010-2013 RT-RK
     11       mips-valgrind (at) rt-rk.com
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26    02111-1307, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Translates MIPS code to IR. */
     32 
     33 #include "libvex_basictypes.h"
     34 #include "libvex_ir.h"
     35 #include "libvex.h"
     36 #include "libvex_guest_mips32.h"
     37 #include "libvex_guest_mips64.h"
     38 
     39 #include "main_util.h"
     40 #include "main_globals.h"
     41 #include "guest_generic_bb_to_IR.h"
     42 #include "guest_mips_defs.h"
     43 
     44 /*------------------------------------------------------------*/
     45 /*---                      Globals                         ---*/
     46 /*------------------------------------------------------------*/
     47 
     48 /* These are set at the start of the translation of a instruction, so
     49    that we don't have to pass them around endlessly. CONST means does
     50    not change during translation of the instruction. */
     51 
     52 /* CONST: what is the host's endianness?  This has to do with float vs
     53    double register accesses on VFP, but it's complex and not properly
     54    thought out. */
     55 static VexEndness host_endness;
     56 
     57 /* Pointer to the guest code area. */
     58 static const UChar *guest_code;
     59 
     60 /* CONST: The guest address for the instruction currently being
     61    translated. */
     62 #if defined(VGP_mips32_linux)
     63 static Addr32 guest_PC_curr_instr;
     64 #else
     65 static Addr64 guest_PC_curr_instr;
     66 #endif
     67 
     68 /* MOD: The IRSB* into which we're generating code. */
     69 static IRSB *irsb;
     70 
     71 /* Is our guest binary 32 or 64bit? Set at each call to
     72    disInstr_MIPS below. */
     73 static Bool mode64 = False;
     74 
     75 /* CPU has FPU and 32 dbl. prec. FP registers. */
     76 static Bool fp_mode64 = False;
     77 
     78 /* Define 1.0 in single and double precision. */
     79 #define ONE_SINGLE 0x3F800000
     80 #define ONE_DOUBLE 0x3FF0000000000000ULL
     81 
     82 /*------------------------------------------------------------*/
     83 /*---                  Debugging output                    ---*/
     84 /*------------------------------------------------------------*/
     85 
     86 #define DIP(format, args...)           \
     87    if (vex_traceflags & VEX_TRACE_FE)  \
     88       vex_printf(format, ## args)
     89 
     90 /*------------------------------------------------------------*/
     91 /*--- Helper bits and pieces for deconstructing the        ---*/
     92 /*--- mips insn stream.                                    ---*/
     93 /*------------------------------------------------------------*/
     94 
     95 /* ---------------- Integer registers ---------------- */
     96 
     97 static UInt integerGuestRegOffset(UInt iregNo)
     98 {
     99    /* Do we care about endianness here?  We do if sub-parts of integer
    100       registers are accessed, but I don't think that ever happens on
    101       MIPS. */
    102    UInt ret;
    103    if (!mode64)
    104       switch (iregNo) {
    105          case 0:
    106             ret = offsetof(VexGuestMIPS32State, guest_r0); break;
    107          case 1:
    108             ret = offsetof(VexGuestMIPS32State, guest_r1); break;
    109          case 2:
    110             ret = offsetof(VexGuestMIPS32State, guest_r2); break;
    111          case 3:
    112             ret = offsetof(VexGuestMIPS32State, guest_r3); break;
    113          case 4:
    114             ret = offsetof(VexGuestMIPS32State, guest_r4); break;
    115          case 5:
    116             ret = offsetof(VexGuestMIPS32State, guest_r5); break;
    117          case 6:
    118             ret = offsetof(VexGuestMIPS32State, guest_r6); break;
    119          case 7:
    120             ret = offsetof(VexGuestMIPS32State, guest_r7); break;
    121          case 8:
    122             ret = offsetof(VexGuestMIPS32State, guest_r8); break;
    123          case 9:
    124             ret = offsetof(VexGuestMIPS32State, guest_r9); break;
    125          case 10:
    126             ret = offsetof(VexGuestMIPS32State, guest_r10); break;
    127          case 11:
    128             ret = offsetof(VexGuestMIPS32State, guest_r11); break;
    129          case 12:
    130             ret = offsetof(VexGuestMIPS32State, guest_r12); break;
    131          case 13:
    132             ret = offsetof(VexGuestMIPS32State, guest_r13); break;
    133          case 14:
    134             ret = offsetof(VexGuestMIPS32State, guest_r14); break;
    135          case 15:
    136             ret = offsetof(VexGuestMIPS32State, guest_r15); break;
    137          case 16:
    138             ret = offsetof(VexGuestMIPS32State, guest_r16); break;
    139          case 17:
    140             ret = offsetof(VexGuestMIPS32State, guest_r17); break;
    141          case 18:
    142             ret = offsetof(VexGuestMIPS32State, guest_r18); break;
    143          case 19:
    144             ret = offsetof(VexGuestMIPS32State, guest_r19); break;
    145          case 20:
    146             ret = offsetof(VexGuestMIPS32State, guest_r20); break;
    147          case 21:
    148             ret = offsetof(VexGuestMIPS32State, guest_r21); break;
    149          case 22:
    150             ret = offsetof(VexGuestMIPS32State, guest_r22); break;
    151          case 23:
    152             ret = offsetof(VexGuestMIPS32State, guest_r23); break;
    153          case 24:
    154             ret = offsetof(VexGuestMIPS32State, guest_r24); break;
    155          case 25:
    156             ret = offsetof(VexGuestMIPS32State, guest_r25); break;
    157          case 26:
    158             ret = offsetof(VexGuestMIPS32State, guest_r26); break;
    159          case 27:
    160             ret = offsetof(VexGuestMIPS32State, guest_r27); break;
    161          case 28:
    162             ret = offsetof(VexGuestMIPS32State, guest_r28); break;
    163          case 29:
    164             ret = offsetof(VexGuestMIPS32State, guest_r29); break;
    165          case 30:
    166             ret = offsetof(VexGuestMIPS32State, guest_r30); break;
    167          case 31:
    168             ret = offsetof(VexGuestMIPS32State, guest_r31); break;
    169          default:
    170             vassert(0);
    171             break;
    172       }
    173    else
    174       switch (iregNo) {
    175          case 0:
    176             ret = offsetof(VexGuestMIPS64State, guest_r0); break;
    177          case 1:
    178             ret = offsetof(VexGuestMIPS64State, guest_r1); break;
    179          case 2:
    180             ret = offsetof(VexGuestMIPS64State, guest_r2); break;
    181          case 3:
    182             ret = offsetof(VexGuestMIPS64State, guest_r3); break;
    183          case 4:
    184             ret = offsetof(VexGuestMIPS64State, guest_r4); break;
    185          case 5:
    186             ret = offsetof(VexGuestMIPS64State, guest_r5); break;
    187          case 6:
    188             ret = offsetof(VexGuestMIPS64State, guest_r6); break;
    189          case 7:
    190             ret = offsetof(VexGuestMIPS64State, guest_r7); break;
    191          case 8:
    192             ret = offsetof(VexGuestMIPS64State, guest_r8); break;
    193          case 9:
    194             ret = offsetof(VexGuestMIPS64State, guest_r9); break;
    195          case 10:
    196             ret = offsetof(VexGuestMIPS64State, guest_r10); break;
    197          case 11:
    198             ret = offsetof(VexGuestMIPS64State, guest_r11); break;
    199          case 12:
    200             ret = offsetof(VexGuestMIPS64State, guest_r12); break;
    201          case 13:
    202             ret = offsetof(VexGuestMIPS64State, guest_r13); break;
    203          case 14:
    204             ret = offsetof(VexGuestMIPS64State, guest_r14); break;
    205          case 15:
    206             ret = offsetof(VexGuestMIPS64State, guest_r15); break;
    207          case 16:
    208             ret = offsetof(VexGuestMIPS64State, guest_r16); break;
    209          case 17:
    210             ret = offsetof(VexGuestMIPS64State, guest_r17); break;
    211          case 18:
    212             ret = offsetof(VexGuestMIPS64State, guest_r18); break;
    213          case 19:
    214             ret = offsetof(VexGuestMIPS64State, guest_r19); break;
    215          case 20:
    216             ret = offsetof(VexGuestMIPS64State, guest_r20); break;
    217          case 21:
    218             ret = offsetof(VexGuestMIPS64State, guest_r21); break;
    219          case 22:
    220             ret = offsetof(VexGuestMIPS64State, guest_r22); break;
    221          case 23:
    222             ret = offsetof(VexGuestMIPS64State, guest_r23); break;
    223          case 24:
    224             ret = offsetof(VexGuestMIPS64State, guest_r24); break;
    225          case 25:
    226             ret = offsetof(VexGuestMIPS64State, guest_r25); break;
    227          case 26:
    228             ret = offsetof(VexGuestMIPS64State, guest_r26); break;
    229          case 27:
    230             ret = offsetof(VexGuestMIPS64State, guest_r27); break;
    231          case 28:
    232             ret = offsetof(VexGuestMIPS64State, guest_r28); break;
    233          case 29:
    234             ret = offsetof(VexGuestMIPS64State, guest_r29); break;
    235          case 30:
    236             ret = offsetof(VexGuestMIPS64State, guest_r30); break;
    237          case 31:
    238             ret = offsetof(VexGuestMIPS64State, guest_r31); break;
    239          default:
    240             vassert(0);
    241             break;
    242       }
    243    return ret;
    244 }
    245 
    246 #if defined(VGP_mips32_linux)
    247 #define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
    248 #else
    249 #define OFFB_PC     offsetof(VexGuestMIPS64State, guest_PC)
    250 #endif
    251 
    252 /* ---------------- Floating point registers ---------------- */
    253 
    254 static UInt floatGuestRegOffset(UInt fregNo)
    255 {
    256    vassert(fregNo < 32);
    257    UInt ret;
    258    if (!mode64)
    259       switch (fregNo) {
    260          case 0:
    261             ret = offsetof(VexGuestMIPS32State, guest_f0); break;
    262          case 1:
    263             ret = offsetof(VexGuestMIPS32State, guest_f1); break;
    264          case 2:
    265             ret = offsetof(VexGuestMIPS32State, guest_f2); break;
    266          case 3:
    267             ret = offsetof(VexGuestMIPS32State, guest_f3); break;
    268          case 4:
    269             ret = offsetof(VexGuestMIPS32State, guest_f4); break;
    270          case 5:
    271             ret = offsetof(VexGuestMIPS32State, guest_f5); break;
    272          case 6:
    273             ret = offsetof(VexGuestMIPS32State, guest_f6); break;
    274          case 7:
    275             ret = offsetof(VexGuestMIPS32State, guest_f7); break;
    276          case 8:
    277             ret = offsetof(VexGuestMIPS32State, guest_f8); break;
    278          case 9:
    279             ret = offsetof(VexGuestMIPS32State, guest_f9); break;
    280          case 10:
    281             ret = offsetof(VexGuestMIPS32State, guest_f10); break;
    282          case 11:
    283             ret = offsetof(VexGuestMIPS32State, guest_f11); break;
    284          case 12:
    285             ret = offsetof(VexGuestMIPS32State, guest_f12); break;
    286          case 13:
    287             ret = offsetof(VexGuestMIPS32State, guest_f13); break;
    288          case 14:
    289             ret = offsetof(VexGuestMIPS32State, guest_f14); break;
    290          case 15:
    291             ret = offsetof(VexGuestMIPS32State, guest_f15); break;
    292          case 16:
    293             ret = offsetof(VexGuestMIPS32State, guest_f16); break;
    294          case 17:
    295             ret = offsetof(VexGuestMIPS32State, guest_f17); break;
    296          case 18:
    297             ret = offsetof(VexGuestMIPS32State, guest_f18); break;
    298          case 19:
    299             ret = offsetof(VexGuestMIPS32State, guest_f19); break;
    300          case 20:
    301             ret = offsetof(VexGuestMIPS32State, guest_f20); break;
    302          case 21:
    303             ret = offsetof(VexGuestMIPS32State, guest_f21); break;
    304          case 22:
    305             ret = offsetof(VexGuestMIPS32State, guest_f22); break;
    306          case 23:
    307             ret = offsetof(VexGuestMIPS32State, guest_f23); break;
    308          case 24:
    309             ret = offsetof(VexGuestMIPS32State, guest_f24); break;
    310          case 25:
    311             ret = offsetof(VexGuestMIPS32State, guest_f25); break;
    312          case 26:
    313             ret = offsetof(VexGuestMIPS32State, guest_f26); break;
    314          case 27:
    315             ret = offsetof(VexGuestMIPS32State, guest_f27); break;
    316          case 28:
    317             ret = offsetof(VexGuestMIPS32State, guest_f28); break;
    318          case 29:
    319             ret = offsetof(VexGuestMIPS32State, guest_f29); break;
    320          case 30:
    321             ret = offsetof(VexGuestMIPS32State, guest_f30); break;
    322          case 31:
    323             ret = offsetof(VexGuestMIPS32State, guest_f31); break;
    324          default:
    325             vassert(0);
    326             break;
    327       }
    328    else
    329       switch (fregNo) {
    330          case 0:
    331             ret = offsetof(VexGuestMIPS64State, guest_f0); break;
    332          case 1:
    333             ret = offsetof(VexGuestMIPS64State, guest_f1); break;
    334          case 2:
    335             ret = offsetof(VexGuestMIPS64State, guest_f2); break;
    336          case 3:
    337             ret = offsetof(VexGuestMIPS64State, guest_f3); break;
    338          case 4:
    339             ret = offsetof(VexGuestMIPS64State, guest_f4); break;
    340          case 5:
    341             ret = offsetof(VexGuestMIPS64State, guest_f5); break;
    342          case 6:
    343             ret = offsetof(VexGuestMIPS64State, guest_f6); break;
    344          case 7:
    345             ret = offsetof(VexGuestMIPS64State, guest_f7); break;
    346          case 8:
    347             ret = offsetof(VexGuestMIPS64State, guest_f8); break;
    348          case 9:
    349             ret = offsetof(VexGuestMIPS64State, guest_f9); break;
    350          case 10:
    351             ret = offsetof(VexGuestMIPS64State, guest_f10); break;
    352          case 11:
    353             ret = offsetof(VexGuestMIPS64State, guest_f11); break;
    354          case 12:
    355             ret = offsetof(VexGuestMIPS64State, guest_f12); break;
    356          case 13:
    357             ret = offsetof(VexGuestMIPS64State, guest_f13); break;
    358          case 14:
    359             ret = offsetof(VexGuestMIPS64State, guest_f14); break;
    360          case 15:
    361             ret = offsetof(VexGuestMIPS64State, guest_f15); break;
    362          case 16:
    363             ret = offsetof(VexGuestMIPS64State, guest_f16); break;
    364          case 17:
    365             ret = offsetof(VexGuestMIPS64State, guest_f17); break;
    366          case 18:
    367             ret = offsetof(VexGuestMIPS64State, guest_f18); break;
    368          case 19:
    369             ret = offsetof(VexGuestMIPS64State, guest_f19); break;
    370          case 20:
    371             ret = offsetof(VexGuestMIPS64State, guest_f20); break;
    372          case 21:
    373             ret = offsetof(VexGuestMIPS64State, guest_f21); break;
    374          case 22:
    375             ret = offsetof(VexGuestMIPS64State, guest_f22); break;
    376          case 23:
    377             ret = offsetof(VexGuestMIPS64State, guest_f23); break;
    378          case 24:
    379             ret = offsetof(VexGuestMIPS64State, guest_f24); break;
    380          case 25:
    381             ret = offsetof(VexGuestMIPS64State, guest_f25); break;
    382          case 26:
    383             ret = offsetof(VexGuestMIPS64State, guest_f26); break;
    384          case 27:
    385             ret = offsetof(VexGuestMIPS64State, guest_f27); break;
    386          case 28:
    387             ret = offsetof(VexGuestMIPS64State, guest_f28); break;
    388          case 29:
    389             ret = offsetof(VexGuestMIPS64State, guest_f29); break;
    390          case 30:
    391             ret = offsetof(VexGuestMIPS64State, guest_f30); break;
    392          case 31:
    393             ret = offsetof(VexGuestMIPS64State, guest_f31); break;
    394          default:
    395             vassert(0);
    396             break;
    397       }
    398    return ret;
    399 }
    400 
    401 /* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
    402 
    403 static UInt accumulatorGuestRegOffset(UInt acNo)
    404 {
    405    vassert(!mode64);
    406    vassert(acNo <= 3);
    407    UInt ret;
    408    switch (acNo) {
    409       case 0:
    410          ret = offsetof(VexGuestMIPS32State, guest_ac0); break;
    411       case 1:
    412          ret = offsetof(VexGuestMIPS32State, guest_ac1); break;
    413       case 2:
    414          ret = offsetof(VexGuestMIPS32State, guest_ac2); break;
    415       case 3:
    416          ret = offsetof(VexGuestMIPS32State, guest_ac3); break;
    417       default:
    418          vassert(0);
    419     break;
    420    }
    421    return ret;
    422 }
    423 
    424 /* Do a endian load of a 32-bit word, regardless of the endianness of the
    425    underlying host. */
    426 static inline UInt getUInt(const UChar * p)
    427 {
    428    UInt w = 0;
    429 #if defined (_MIPSEL)
    430    w = (w << 8) | p[3];
    431    w = (w << 8) | p[2];
    432    w = (w << 8) | p[1];
    433    w = (w << 8) | p[0];
    434 #elif defined (_MIPSEB)
    435    w = (w << 8) | p[0];
    436    w = (w << 8) | p[1];
    437    w = (w << 8) | p[2];
    438    w = (w << 8) | p[3];
    439 #endif
    440    return w;
    441 }
    442 
    443 #define BITS2(_b1,_b0) \
    444    (((_b1) << 1) | (_b0))
    445 
    446 #define BITS3(_b2,_b1,_b0)                      \
    447   (((_b2) << 2) | ((_b1) << 1) | (_b0))
    448 
    449 #define BITS4(_b3,_b2,_b1,_b0) \
    450    (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
    451 
    452 #define BITS5(_b4,_b3,_b2,_b1,_b0)  \
    453    (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
    454 
    455 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
    456    ((BITS2((_b5),(_b4)) << 4) \
    457     | BITS4((_b3),(_b2),(_b1),(_b0)))
    458 
    459 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
    460    ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
    461     | BITS4((_b3),(_b2),(_b1),(_b0)))
    462 
    463 #define LOAD_STORE_PATTERN \
    464    t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
    465       if(!mode64) \
    466          assign(t1, binop(Iop_Add32, getIReg(rs), \
    467                                      mkU32(extend_s_16to32(imm)))); \
    468       else \
    469          assign(t1, binop(Iop_Add64, getIReg(rs), \
    470                                      mkU64(extend_s_16to64(imm)))); \
    471 
    472 #define LOADX_STORE_PATTERN \
    473    t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
    474       if(!mode64) \
    475          assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
    476       else \
    477          assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
    478 
    479 #define LWX_SWX_PATTERN64 \
    480    t2 = newTemp(Ity_I64); \
    481    assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
    482    t4 = newTemp(Ity_I32); \
    483    assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
    484                                       mkexpr(t1), mkU64(0x3))));
    485 
    486 #define LWX_SWX_PATTERN64_1 \
    487    t2 = newTemp(Ity_I64); \
    488    assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
    489    t4 = newTemp(Ity_I64); \
    490    assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
    491 
    492 #define LWX_SWX_PATTERN \
    493    t2 = newTemp(Ity_I32); \
    494    assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
    495    t4 = newTemp(Ity_I32); \
    496    assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
    497 
    498 #define SXXV_PATTERN(op) \
    499    putIReg(rd, binop(op, \
    500          getIReg(rt), \
    501             unop(Iop_32to8, \
    502                binop(Iop_And32, \
    503                   getIReg(rs), \
    504                   mkU32(0x0000001F) \
    505                ) \
    506             ) \
    507          ) \
    508       )
    509 
    510 #define SXXV_PATTERN64(op) \
    511    putIReg(rd, mkWidenFrom32(ty, binop(op, \
    512            mkNarrowTo32(ty, getIReg(rt)), \
    513              unop(Iop_32to8, \
    514                 binop(Iop_And32, \
    515                    mkNarrowTo32(ty, getIReg(rs)), \
    516                    mkU32(0x0000001F) \
    517                 ) \
    518              ) \
    519           ), True \
    520        ))
    521 
    522 #define SXX_PATTERN(op) \
    523    putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
    524 
    525 #define ALU_PATTERN(op) \
    526    putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
    527 
    528 #define ALUI_PATTERN(op) \
    529    putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
    530 
    531 #define ALUI_PATTERN64(op) \
    532    putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
    533 
    534 #define ALU_PATTERN64(op) \
    535    putIReg(rd, mkWidenFrom32(ty, binop(op, \
    536                              mkNarrowTo32(ty, getIReg(rs)), \
    537                              mkNarrowTo32(ty, getIReg(rt))), True));
    538 
    539 #define FP_CONDITIONAL_CODE \
    540    t3 = newTemp(Ity_I32);   \
    541    assign(t3, binop(Iop_And32, \
    542                  IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
    543                              binop(Iop_Shr32, getFCSR(), mkU8(23)), \
    544                              binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
    545                  mkU32(0x1)));
    546 
    547 #define ILLEGAL_INSTRUCTON \
    548    putPC(mkU32(guest_PC_curr_instr + 4)); \
    549    dres.jk_StopHere = Ijk_SigILL; \
    550    dres.whatNext    = Dis_StopHere;
    551 
    552 /*------------------------------------------------------------*/
    553 /*---                  Field helpers                       ---*/
    554 /*------------------------------------------------------------*/
    555 
    556 static UInt get_opcode(UInt mipsins)
    557 {
    558    return (0xFC000000 & mipsins) >> 26;
    559 }
    560 
    561 static UInt get_rs(UInt mipsins)
    562 {
    563    return (0x03E00000 & mipsins) >> 21;
    564 }
    565 
    566 static UInt get_rt(UInt mipsins)
    567 {
    568    return (0x001F0000 & mipsins) >> 16;
    569 }
    570 
    571 static UInt get_imm(UInt mipsins)
    572 {
    573    return (0x0000FFFF & mipsins);
    574 }
    575 
    576 static UInt get_instr_index(UInt mipsins)
    577 {
    578    return (0x03FFFFFF & mipsins);
    579 }
    580 
    581 static UInt get_rd(UInt mipsins)
    582 {
    583    return (0x0000F800 & mipsins) >> 11;
    584 }
    585 
    586 static UInt get_sa(UInt mipsins)
    587 {
    588    return (0x000007C0 & mipsins) >> 6;
    589 }
    590 
    591 static UInt get_function(UInt mipsins)
    592 {
    593    return (0x0000003F & mipsins);
    594 }
    595 
    596 static UInt get_ft(UInt mipsins)
    597 {
    598    return (0x001F0000 & mipsins) >> 16;
    599 }
    600 
    601 static UInt get_fs(UInt mipsins)
    602 {
    603    return (0x0000F800 & mipsins) >> 11;
    604 }
    605 
    606 static UInt get_fd(UInt mipsins)
    607 {
    608    return (0x000007C0 & mipsins) >> 6;
    609 }
    610 
    611 static UInt get_mov_cc(UInt mipsins)
    612 {
    613    return (0x001C0000 & mipsins) >> 18;
    614 }
    615 
    616 static UInt get_bc1_cc(UInt mipsins)
    617 {
    618    return (0x001C0000 & mipsins) >> 18;
    619 }
    620 
    621 static UInt get_fpc_cc(UInt mipsins)
    622 {
    623    return (0x00000700 & mipsins) >> 8;
    624 }
    625 
    626 static UInt get_tf(UInt mipsins)
    627 {
    628    return (0x00010000 & mipsins) >> 16;
    629 }
    630 
    631 static UInt get_nd(UInt mipsins)
    632 {
    633    return (0x00020000 & mipsins) >> 17;
    634 }
    635 
    636 static UInt get_fmt(UInt mipsins)
    637 {
    638    return (0x03E00000 & mipsins) >> 21;
    639 }
    640 
    641 static UInt get_FC(UInt mipsins)
    642 {
    643    return (0x000000F0 & mipsins) >> 4;
    644 }
    645 
    646 static UInt get_cond(UInt mipsins)
    647 {
    648    return (0x0000000F & mipsins);
    649 }
    650 
    651 /* for break & syscall */
    652 static UInt get_code(UInt mipsins)
    653 {
    654    return (0xFFC0 & mipsins) >> 6;
    655 }
    656 
    657 static UInt get_lsb(UInt mipsins)
    658 {
    659    return (0x7C0 & mipsins) >> 6;
    660 }
    661 
    662 static UInt get_msb(UInt mipsins)
    663 {
    664    return (0x0000F800 & mipsins) >> 11;
    665 }
    666 
    667 static UInt get_rot(UInt mipsins)
    668 {
    669    return (0x00200000 & mipsins) >> 21;
    670 }
    671 
    672 static UInt get_rotv(UInt mipsins)
    673 {
    674    return (0x00000040 & mipsins) >> 6;
    675 }
    676 
    677 static UInt get_sel(UInt mipsins)
    678 {
    679    return (0x00000007 & mipsins);
    680 }
    681 
    682 /* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
    683    except for MFHI and MFLO. */
    684 static UInt get_acNo(UInt mipsins)
    685 {
    686    return (0x00001800 & mipsins) >> 11;
    687 }
    688 
    689 /* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
    690 static UInt get_acNo_mfhilo(UInt mipsins)
    691 {
    692    return (0x00600000 & mipsins) >> 21;
    693 }
    694 
    695 /* Get mask field (helper function for wrdsp instruction). */
    696 static UInt get_wrdspMask(UInt mipsins)
    697 {
    698    return (0x001ff800 & mipsins) >> 11;
    699 }
    700 
    701 /* Get mask field (helper function for rddsp instruction). */
    702 static UInt get_rddspMask(UInt mipsins)
    703 {
    704    return (0x03ff0000 & mipsins) >> 16;
    705 }
    706 
    707 /* Get shift field (helper function for DSP ASE instructions). */
    708 static UInt get_shift(UInt mipsins)
    709 {
    710    return (0x03f00000 & mipsins) >> 20;
    711 }
    712 
    713 /* Get immediate field for DSP ASE instructions. */
    714 static UInt get_dspImm(UInt mipsins)
    715 {
    716    return (0x03ff0000 & mipsins) >> 16;
    717 }
    718 
    719 static Bool branch_or_jump(const UChar * addr)
    720 {
    721    UInt fmt;
    722    UInt cins = getUInt(addr);
    723 
    724    UInt opcode = get_opcode(cins);
    725    UInt rt = get_rt(cins);
    726    UInt function = get_function(cins);
    727 
    728    /* bgtz, blez, bne, beq, jal */
    729    if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
    730        || opcode == 0x03 || opcode == 0x02) {
    731       return True;
    732    }
    733 
    734    /* bgez */
    735    if (opcode == 0x01 && rt == 0x01) {
    736       return True;
    737    }
    738 
    739    /* bgezal */
    740    if (opcode == 0x01 && rt == 0x11) {
    741       return True;
    742    }
    743 
    744    /* bltzal */
    745    if (opcode == 0x01 && rt == 0x10) {
    746       return True;
    747    }
    748 
    749    /* bltz */
    750    if (opcode == 0x01 && rt == 0x00) {
    751       return True;
    752    }
    753 
    754    /* jalr */
    755    if (opcode == 0x00 && function == 0x09) {
    756       return True;
    757    }
    758 
    759    /* jr */
    760    if (opcode == 0x00 && function == 0x08) {
    761       return True;
    762    }
    763 
    764    if (opcode == 0x11) {
    765       /*bc1f & bc1t */
    766       fmt = get_fmt(cins);
    767       if (fmt == 0x08) {
    768          return True;
    769       }
    770    }
    771 
    772    /* bposge32 */
    773    if (opcode == 0x01 && rt == 0x1c) {
    774       return True;
    775    }
    776 
    777    /* Cavium Specific instructions. */
    778    if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
    779        /* BBIT0, BBIT1, BBIT032, BBIT132 */
    780       return True;
    781    }
    782 
    783    return False;
    784 }
    785 
    786 static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
    787 {
    788    UInt cins = getUInt(addr);
    789 
    790    UInt opcode = get_opcode(cins);
    791    UInt rt = get_rt(cins);
    792    UInt function = get_function(cins);
    793 
    794    /* jal */
    795    if (opcode == 0x02) {
    796       return True;
    797    }
    798 
    799    /* bgezal */
    800    if (opcode == 0x01 && rt == 0x11) {
    801       return True;
    802    }
    803 
    804    /* bltzal */
    805    if (opcode == 0x01 && rt == 0x10) {
    806       return True;
    807    }
    808 
    809    /* jalr */
    810    if (opcode == 0x00 && function == 0x09) {
    811       return True;
    812    }
    813 
    814    return False;
    815 }
    816 
    817 static Bool branch_or_link_likely(const UChar * addr)
    818 {
    819    UInt cins = getUInt(addr);
    820    UInt opcode = get_opcode(cins);
    821    UInt rt = get_rt(cins);
    822 
    823    /* bgtzl, blezl, bnel, beql */
    824    if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
    825       return True;
    826 
    827    /* bgezl */
    828    if (opcode == 0x01 && rt == 0x03)
    829       return True;
    830 
    831    /* bgezall */
    832    if (opcode == 0x01 && rt == 0x13)
    833       return True;
    834 
    835    /* bltzall */
    836    if (opcode == 0x01 && rt == 0x12)
    837       return True;
    838 
    839    /* bltzl */
    840    if (opcode == 0x01 && rt == 0x02)
    841       return True;
    842 
    843    return False;
    844 }
    845 
    846 /*------------------------------------------------------------*/
    847 /*--- Helper bits and pieces for creating IR fragments.    ---*/
    848 /*------------------------------------------------------------*/
    849 
    850 static IRExpr *mkU8(UInt i)
    851 {
    852    vassert(i < 256);
    853    return IRExpr_Const(IRConst_U8((UChar) i));
    854 }
    855 
    856 /* Create an expression node for a 16-bit integer constant. */
    857 static IRExpr *mkU16(UInt i)
    858 {
    859    return IRExpr_Const(IRConst_U16(i));
    860 }
    861 
    862 /* Create an expression node for a 32-bit integer constant. */
    863 static IRExpr *mkU32(UInt i)
    864 {
    865    return IRExpr_Const(IRConst_U32(i));
    866 }
    867 
    868 /* Create an expression node for a 64-bit integer constant. */
    869 static IRExpr *mkU64(ULong i)
    870 {
    871    return IRExpr_Const(IRConst_U64(i));
    872 }
    873 
    874 static IRExpr *mkexpr(IRTemp tmp)
    875 {
    876    return IRExpr_RdTmp(tmp);
    877 }
    878 
    879 static IRExpr *unop(IROp op, IRExpr * a)
    880 {
    881    return IRExpr_Unop(op, a);
    882 }
    883 
    884 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
    885 {
    886    return IRExpr_Binop(op, a1, a2);
    887 }
    888 
    889 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
    890 {
    891    return IRExpr_Triop(op, a1, a2, a3);
    892 }
    893 
    894 static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
    895                      IRExpr * a4 )
    896 {
    897    return IRExpr_Qop(op, a1, a2, a3, a4);
    898 }
    899 
    900 static IRExpr *load(IRType ty, IRExpr * addr)
    901 {
    902    IRExpr *load1 = NULL;
    903 #if defined (_MIPSEL)
    904    load1 = IRExpr_Load(Iend_LE, ty, addr);
    905 #elif defined (_MIPSEB)
    906    load1 = IRExpr_Load(Iend_BE, ty, addr);
    907 #endif
    908    return load1;
    909 }
    910 
    911 /* Add a statement to the list held by "irsb". */
    912 static void stmt(IRStmt * st)
    913 {
    914    addStmtToIRSB(irsb, st);
    915 }
    916 
    917 static void assign(IRTemp dst, IRExpr * e)
    918 {
    919    stmt(IRStmt_WrTmp(dst, e));
    920 }
    921 
    922 static void store(IRExpr * addr, IRExpr * data)
    923 {
    924 #if defined (_MIPSEL)
    925    stmt(IRStmt_Store(Iend_LE, addr, data));
    926 #elif defined (_MIPSEB)
    927    stmt(IRStmt_Store(Iend_BE, addr, data));
    928 #endif
    929 }
    930 
    931 /* Generate a new temporary of the given type. */
    932 static IRTemp newTemp(IRType ty)
    933 {
    934    vassert(isPlausibleIRType(ty));
    935    return newIRTemp(irsb->tyenv, ty);
    936 }
    937 
    938 /* Generate an expression for SRC rotated right by ROT. */
    939 static IRExpr *genROR32(IRExpr * src, Int rot)
    940 {
    941    vassert(rot >= 0 && rot < 32);
    942    if (rot == 0)
    943       return src;
    944    return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
    945                           binop(Iop_Shr32, src, mkU8(rot)));
    946 }
    947 
    948 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
    949 {
    950    IRTemp t0 = newTemp(Ity_I8);
    951    IRTemp t1 = newTemp(Ity_I8);
    952 
    953    assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
    954    assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
    955    return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
    956                           binop(Iop_Shr32, src, mkexpr(t0)));
    957 }
    958 
    959 static UShort extend_s_10to16(UInt x)
    960 {
    961    return (UShort) ((((Int) x) << 22) >> 22);
    962 }
    963 
    964 static ULong extend_s_10to32(UInt x)
    965 {
    966    return (ULong)((((Long) x) << 22) >> 22);
    967 }
    968 
    969 static ULong extend_s_10to64(UInt x)
    970 {
    971    return (ULong)((((Long) x) << 54) >> 54);
    972 }
    973 
    974 static UInt extend_s_16to32(UInt x)
    975 {
    976    return (UInt) ((((Int) x) << 16) >> 16);
    977 }
    978 
    979 static UInt extend_s_18to32(UInt x)
    980 {
    981    return (UInt) ((((Int) x) << 14) >> 14);
    982 }
    983 
    984 static ULong extend_s_16to64 ( UInt x )
    985 {
    986    return (ULong) ((((Long) x) << 48) >> 48);
    987 }
    988 
    989 static ULong extend_s_18to64 ( UInt x )
    990 {
    991    return (ULong) ((((Long) x) << 46) >> 46);
    992 }
    993 
    994 static ULong extend_s_32to64 ( UInt x )
    995 {
    996    return (ULong) ((((Long) x) << 32) >> 32);
    997 }
    998 
    999 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
   1000 {
   1001    vassert(dres->whatNext    == Dis_Continue);
   1002    vassert(dres->len         == 0);
   1003    vassert(dres->continueAt  == 0);
   1004    vassert(dres->jk_StopHere == Ijk_INVALID);
   1005    dres->whatNext    = Dis_StopHere;
   1006    dres->jk_StopHere = kind;
   1007    stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
   1008 }
   1009 
   1010 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
   1011 {
   1012    vassert(dres->whatNext    == Dis_Continue);
   1013    vassert(dres->len         == 0);
   1014    vassert(dres->continueAt  == 0);
   1015    vassert(dres->jk_StopHere == Ijk_INVALID);
   1016    dres->whatNext    = Dis_StopHere;
   1017    dres->jk_StopHere = kind;
   1018    stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
   1019 }
   1020 
   1021 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
   1022    This function should be called before any other operation if widening
   1023    multiplications are used. */
   1024 static IRExpr *getAcc(UInt acNo)
   1025 {
   1026    vassert(!mode64);
   1027    vassert(acNo <= 3);
   1028    return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
   1029 }
   1030 
   1031 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE
   1032    instructions). */
   1033 static IRExpr *getDSPControl(void)
   1034 {
   1035    vassert(!mode64);
   1036    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
   1037 }
   1038 
   1039 /* Put value to DSPControl register. Expression e is written to DSPControl as
   1040    is. If only certain bits of DSPControl need to be changed, it should be done
   1041    before calling putDSPControl(). It could be done by reading DSPControl and
   1042    ORing it with appropriate mask. */
   1043 static void putDSPControl(IRExpr * e)
   1044 {
   1045    vassert(!mode64);
   1046    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
   1047 }
   1048 
   1049 /* Fetch a byte from the guest insn stream. */
   1050 static UChar getIByte(Int delta)
   1051 {
   1052    return guest_code[delta];
   1053 }
   1054 
   1055 static IRExpr *getIReg(UInt iregNo)
   1056 {
   1057    if (0 == iregNo) {
   1058       return mode64 ? mkU64(0x0) : mkU32(0x0);
   1059    } else {
   1060       IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1061       vassert(iregNo < 32);
   1062       return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
   1063    }
   1064 }
   1065 
   1066 static IRExpr *getHI(void)
   1067 {
   1068    if (mode64)
   1069       return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
   1070    else
   1071       return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
   1072 }
   1073 
   1074 static IRExpr *getLO(void)
   1075 {
   1076    if (mode64)
   1077       return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
   1078    else
   1079       return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
   1080 }
   1081 
   1082 static IRExpr *getFCSR(void)
   1083 {
   1084    if (mode64)
   1085       return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
   1086    else
   1087       return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
   1088 }
   1089 
   1090 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
   1091 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
   1092 {
   1093   UInt pos = byte_pos * 8;
   1094   if (mode64)
   1095       return unop(Iop_64to8, binop(Iop_And64,
   1096                                    binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
   1097                                    mkU64(0xFF)));
   1098    else
   1099       return unop(Iop_32to8, binop(Iop_And32,
   1100                                    binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
   1101                                    mkU32(0xFF)));
   1102 }
   1103 
   1104 static void putFCSR(IRExpr * e)
   1105 {
   1106    if (mode64)
   1107       stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
   1108    else
   1109       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
   1110 }
   1111 
   1112 /* fs   - fpu source register number.
   1113    inst - fpu instruction that needs to be executed.
   1114    sz32 - size of source register.
   1115    opN  - number of operads:
   1116           1 - unary operation.
   1117           2 - binary operation. */
   1118 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
   1119 {
   1120    IRDirty *d;
   1121    IRTemp fcsr = newTemp(Ity_I32);
   1122    /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
   1123    if (fp_mode64)
   1124       d = unsafeIRDirty_1_N(fcsr, 0,
   1125                             "mips_dirtyhelper_calculate_FCSR_fp64",
   1126                             &mips_dirtyhelper_calculate_FCSR_fp64,
   1127                             mkIRExprVec_4(IRExpr_BBPTR(),
   1128                                           mkU32(fs),
   1129                                           mkU32(ft),
   1130                                           mkU32(inst)));
   1131    else
   1132       d = unsafeIRDirty_1_N(fcsr, 0,
   1133                             "mips_dirtyhelper_calculate_FCSR_fp32",
   1134                             &mips_dirtyhelper_calculate_FCSR_fp32,
   1135                             mkIRExprVec_4(IRExpr_BBPTR(),
   1136                                           mkU32(fs),
   1137                                           mkU32(ft),
   1138                                           mkU32(inst)));
   1139 
   1140    if (opN == 1) {  /* Unary operation. */
   1141       /* Declare we're reading guest state. */
   1142       if (sz32 || fp_mode64)
   1143          d->nFxState = 2;
   1144       else
   1145          d->nFxState = 3;
   1146       vex_bzero(&d->fxState, sizeof(d->fxState));
   1147 
   1148       d->fxState[0].fx     = Ifx_Read;  /* read */
   1149       if (mode64)
   1150          d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
   1151       else
   1152          d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
   1153       d->fxState[0].size   = sizeof(UInt);
   1154       d->fxState[1].fx     = Ifx_Read;  /* read */
   1155       d->fxState[1].offset = floatGuestRegOffset(fs);
   1156       d->fxState[1].size   = sizeof(ULong);
   1157 
   1158       if (!(sz32 || fp_mode64)) {
   1159          d->fxState[2].fx     = Ifx_Read;  /* read */
   1160          d->fxState[2].offset = floatGuestRegOffset(fs+1);
   1161          d->fxState[2].size   = sizeof(ULong);
   1162       }
   1163    } else if (opN == 2) {  /* Binary operation. */
   1164       /* Declare we're reading guest state. */
   1165       if (sz32 || fp_mode64)
   1166          d->nFxState = 3;
   1167       else
   1168          d->nFxState = 5;
   1169       vex_bzero(&d->fxState, sizeof(d->fxState));
   1170 
   1171       d->fxState[0].fx     = Ifx_Read;  /* read */
   1172       if (mode64)
   1173          d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
   1174       else
   1175          d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
   1176       d->fxState[0].size   = sizeof(UInt);
   1177       d->fxState[1].fx     = Ifx_Read;  /* read */
   1178       d->fxState[1].offset = floatGuestRegOffset(fs);
   1179       d->fxState[1].size   = sizeof(ULong);
   1180       d->fxState[2].fx     = Ifx_Read;  /* read */
   1181       d->fxState[2].offset = floatGuestRegOffset(ft);
   1182       d->fxState[2].size   = sizeof(ULong);
   1183 
   1184       if (!(sz32 || fp_mode64)) {
   1185          d->fxState[3].fx     = Ifx_Read;  /* read */
   1186          d->fxState[3].offset = floatGuestRegOffset(fs+1);
   1187          d->fxState[3].size   = sizeof(ULong);
   1188          d->fxState[4].fx     = Ifx_Read;  /* read */
   1189          d->fxState[4].offset = floatGuestRegOffset(ft+1);
   1190          d->fxState[4].size   = sizeof(ULong);
   1191       }
   1192    }
   1193 
   1194    stmt(IRStmt_Dirty(d));
   1195 
   1196    putFCSR(mkexpr(fcsr));
   1197 }
   1198 
   1199 static IRExpr *getULR(void)
   1200 {
   1201    if (mode64)
   1202       return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
   1203    else
   1204       return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
   1205 }
   1206 
   1207 static void putIReg(UInt archreg, IRExpr * e)
   1208 {
   1209    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1210    vassert(archreg < 32);
   1211    vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
   1212    if (archreg != 0)
   1213       stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
   1214 }
   1215 
   1216 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
   1217 {
   1218    vassert(ty == Ity_I32 || ty == Ity_I64);
   1219    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
   1220 }
   1221 
   1222 static void putLO(IRExpr * e)
   1223 {
   1224    if (mode64) {
   1225       stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
   1226    } else {
   1227       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
   1228    /* Add value to lower 32 bits of ac0 to maintain compatibility between
   1229       regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
   1230       unchanged. */
   1231       IRTemp t_lo = newTemp(Ity_I32);
   1232       IRTemp t_hi = newTemp(Ity_I32);
   1233       assign(t_lo, e);
   1234       assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
   1235       stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
   1236            binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
   1237    }
   1238 }
   1239 
   1240 static void putHI(IRExpr * e)
   1241 {
   1242    if (mode64) {
   1243       stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
   1244    } else {
   1245       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
   1246    /* Add value to higher 32 bits of ac0 to maintain compatibility between
   1247       regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
   1248       unchanged. */
   1249       IRTemp t_lo = newTemp(Ity_I32);
   1250       IRTemp t_hi = newTemp(Ity_I32);
   1251       assign(t_hi, e);
   1252       assign(t_lo, unop(Iop_64to32, getAcc(0)));
   1253       stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
   1254            binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
   1255    }
   1256 }
   1257 
   1258 /* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
   1259 static void putAcc(UInt acNo, IRExpr * e)
   1260 {
   1261    vassert(!mode64);
   1262    vassert(acNo <= 3);
   1263    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
   1264    stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
   1265 /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
   1266    between MIPS32 and MIPS DSP ASE insn sets. */
   1267    if (0 == acNo) {
   1268      putLO(unop(Iop_64to32, e));
   1269      putHI(unop(Iop_64HIto32, e));
   1270    }
   1271 }
   1272 
   1273 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
   1274 {
   1275    vassert(ty == Ity_I32 || ty == Ity_I64);
   1276    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
   1277 }
   1278 
   1279 static void putPC(IRExpr * e)
   1280 {
   1281    stmt(IRStmt_Put(OFFB_PC, e));
   1282 }
   1283 
   1284 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
   1285 {
   1286    vassert(ty == Ity_I32 || ty == Ity_I64);
   1287    if (ty == Ity_I32)
   1288       return src;
   1289    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
   1290 }
   1291 
   1292 /* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
   1293    of these combinations make sense. */
   1294 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
   1295 {
   1296    IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
   1297    if (src_ty == dst_ty)
   1298       return e;
   1299    if (src_ty == Ity_I32 && dst_ty == Ity_I16)
   1300       return unop(Iop_32to16, e);
   1301    if (src_ty == Ity_I32 && dst_ty == Ity_I8)
   1302       return unop(Iop_32to8, e);
   1303    if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
   1304       vassert(mode64);
   1305       return unop(Iop_64to8, e);
   1306    }
   1307    if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
   1308       vassert(mode64);
   1309       return unop(Iop_64to16, e);
   1310    }
   1311    vpanic("narrowTo(mips)");
   1312    return 0;
   1313 }
   1314 
   1315 static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
   1316 {
   1317    vassert(ty == Ity_F32 || ty == Ity_F64);
   1318    if (ty == Ity_F64) {
   1319       IRTemp t0, t1;
   1320       t0 = newTemp(Ity_I64);
   1321       t1 = newTemp(Ity_I32);
   1322       assign(t0, unop(Iop_ReinterpF64asI64, src));
   1323       assign(t1, unop(Iop_64to32, mkexpr(t0)));
   1324       return unop(Iop_ReinterpI32asF32, mkexpr(t1));
   1325    } else
   1326       return src;
   1327 }
   1328 
   1329 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
   1330 {
   1331    vassert(ty == Ity_F32 || ty == Ity_F64);
   1332    if (ty == Ity_F64) {
   1333       IRTemp t0 = newTemp(Ity_I32);
   1334       IRTemp t1 = newTemp(Ity_I64);
   1335       assign(t0, unop(Iop_ReinterpF32asI32, src));
   1336       assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
   1337       return unop(Iop_ReinterpI64asF64, mkexpr(t1));
   1338    } else
   1339       return src;
   1340 }
   1341 
   1342 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
   1343 {
   1344    ULong branch_offset;
   1345    IRTemp t0;
   1346 
   1347    /* PC = PC + (SignExtend(signed_immed_24) << 2)
   1348       An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
   1349       is added to the address of the instruction following
   1350       the branch (not the branch itself), in the branch delay slot, to form
   1351       a PC-relative effective target address. */
   1352    if (mode64)
   1353       branch_offset = extend_s_18to64(imm << 2);
   1354    else
   1355       branch_offset = extend_s_18to32(imm << 2);
   1356 
   1357    t0 = newTemp(Ity_I1);
   1358    assign(t0, guard);
   1359 
   1360    if (mode64)
   1361       stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
   1362                        IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
   1363    else
   1364       stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
   1365                        IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
   1366 
   1367    irsb->jumpkind = Ijk_Boring;
   1368 
   1369    if (mode64)
   1370       return mkU64(guest_PC_curr_instr + 4 + branch_offset);
   1371    else
   1372       return mkU32(guest_PC_curr_instr + 4 + branch_offset);
   1373 }
   1374 
   1375 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
   1376 {
   1377    ULong branch_offset;
   1378    IRTemp t0;
   1379 
   1380    if (link) {  /* LR (GPR31) = addr of the 2nd instr after branch instr */
   1381       if (mode64)
   1382          putIReg(31, mkU64(guest_PC_curr_instr + 8));
   1383       else
   1384          putIReg(31, mkU32(guest_PC_curr_instr + 8));
   1385    }
   1386 
   1387    /* PC = PC + (SignExtend(signed_immed_24) << 2)
   1388       An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
   1389       is added to the address of the instruction following
   1390       the branch (not the branch itself), in the branch delay slot, to form
   1391       a PC-relative effective target address. */
   1392 
   1393    if (mode64)
   1394       branch_offset = extend_s_18to64(imm << 2);
   1395    else
   1396       branch_offset = extend_s_18to32(imm << 2);
   1397 
   1398    t0 = newTemp(Ity_I1);
   1399    assign(t0, guard);
   1400    if (mode64)
   1401       *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
   1402                          IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
   1403                          OFFB_PC);
   1404    else
   1405       *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
   1406                          IRConst_U32(guest_PC_curr_instr + 4 +
   1407                                      (UInt) branch_offset), OFFB_PC);
   1408 }
   1409 
   1410 static IRExpr *getFReg(UInt fregNo)
   1411 {
   1412    vassert(fregNo < 32);
   1413    IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
   1414    return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
   1415 }
   1416 
   1417 static IRExpr *getDReg(UInt dregNo)
   1418 {
   1419    vassert(dregNo < 32);
   1420    if (fp_mode64) {
   1421       return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
   1422    } else {
   1423       /* Read a floating point register pair and combine their contents into a
   1424          64-bit value */
   1425       IRTemp t0 = newTemp(Ity_F32);
   1426       IRTemp t1 = newTemp(Ity_F32);
   1427       IRTemp t2 = newTemp(Ity_F64);
   1428       IRTemp t3 = newTemp(Ity_I32);
   1429       IRTemp t4 = newTemp(Ity_I32);
   1430       IRTemp t5 = newTemp(Ity_I64);
   1431 
   1432       assign(t0, getFReg(dregNo));
   1433       assign(t1, getFReg(dregNo + 1));
   1434 
   1435       assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
   1436       assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
   1437       assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
   1438       assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
   1439 
   1440       return mkexpr(t2);
   1441    }
   1442 }
   1443 
   1444 static void putFReg(UInt dregNo, IRExpr * e)
   1445 {
   1446    vassert(dregNo < 32);
   1447    IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
   1448    vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
   1449    stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
   1450 }
   1451 
   1452 static void putDReg(UInt dregNo, IRExpr * e)
   1453 {
   1454    if (fp_mode64) {
   1455       vassert(dregNo < 32);
   1456       IRType ty = Ity_F64;
   1457       vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
   1458       stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
   1459    } else {
   1460       vassert(dregNo < 32);
   1461       vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1462       IRTemp t1 = newTemp(Ity_F64);
   1463       IRTemp t4 = newTemp(Ity_I32);
   1464       IRTemp t5 = newTemp(Ity_I32);
   1465       IRTemp t6 = newTemp(Ity_I64);
   1466       assign(t1, e);
   1467       assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
   1468       assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  /* hi */
   1469       assign(t5, unop(Iop_64to32, mkexpr(t6)));    /* lo */
   1470       putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
   1471       putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
   1472    }
   1473 }
   1474 
   1475 static void setFPUCondCode(IRExpr * e, UInt cc)
   1476 {
   1477    if (cc == 0) {
   1478       putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
   1479       putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
   1480    } else {
   1481       putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
   1482                                binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
   1483       putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
   1484    }
   1485 }
   1486 
   1487 static IRExpr* get_IR_roundingmode ( void )
   1488 {
   1489 /*
   1490    rounding mode | MIPS | IR
   1491    ------------------------
   1492    to nearest    | 00  | 00
   1493    to zero       | 01  | 11
   1494    to +infinity  | 10  | 10
   1495    to -infinity  | 11  | 01
   1496 */
   1497    IRTemp rm_MIPS = newTemp(Ity_I32);
   1498    /* Last two bits in FCSR are rounding mode. */
   1499 
   1500    if (mode64)
   1501       assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
   1502                                        guest_FCSR), Ity_I32), mkU32(3)));
   1503    else
   1504       assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
   1505                                        guest_FCSR), Ity_I32), mkU32(3)));
   1506 
   1507    /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
   1508 
   1509    return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
   1510                 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
   1511 }
   1512 
   1513 /* sz, ULong -> IRExpr */
   1514 static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
   1515 {
   1516    vassert(ty == Ity_I32 || ty == Ity_I64);
   1517    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
   1518 }
   1519 
   1520 static IRConst *mkSzConst ( IRType ty, ULong imm64 )
   1521 {
   1522    vassert(ty == Ity_I32 || ty == Ity_I64);
   1523    return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
   1524 }
   1525 
   1526 /* Make sure we get valid 32 and 64bit addresses */
   1527 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
   1528 {
   1529    vassert(ty == Ity_I32 || ty == Ity_I64);
   1530    return (ty == Ity_I64 ? (Addr64) addr :
   1531                            (Addr64) extend_s_32to64(toUInt(addr)));
   1532 }
   1533 
   1534 /* Shift and Rotate instructions for MIPS64 */
   1535 static Bool dis_instr_shrt ( UInt theInstr )
   1536 {
   1537    UInt opc2 = get_function(theInstr);
   1538    UChar regRs = get_rs(theInstr);
   1539    UChar regRt = get_rt(theInstr);
   1540    UChar regRd = get_rd(theInstr);
   1541    UChar uImmsa = get_sa(theInstr);
   1542    Long sImmsa = extend_s_16to64(uImmsa);
   1543    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1544    IRTemp tmp = newTemp(ty);
   1545    IRTemp tmpOr = newTemp(ty);
   1546    IRTemp tmpRt = newTemp(ty);
   1547    IRTemp tmpRs = newTemp(ty);
   1548    IRTemp tmpRd = newTemp(ty);
   1549 
   1550    assign(tmpRs, getIReg(regRs));
   1551    assign(tmpRt, getIReg(regRt));
   1552 
   1553    switch (opc2) {
   1554       case 0x3A:
   1555          if ((regRs & 0x01) == 0) {
   1556             /* Doubleword Shift Right Logical - DSRL; MIPS64 */
   1557             DIP("dsrl r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1558             assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
   1559             putIReg(regRd, mkexpr(tmpRd));
   1560          } else if ((regRs & 0x01) == 1) {
   1561             /* Doubleword Rotate Right - DROTR; MIPS64r2 */
   1562             vassert(mode64);
   1563             DIP("drotr r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1564             IRTemp tmpL = newTemp(ty);
   1565             IRTemp tmpR = newTemp(ty);
   1566             assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
   1567             assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
   1568             assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
   1569             assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
   1570             putIReg(regRd, mkexpr(tmpRd));
   1571          } else
   1572             return False;
   1573          break;
   1574 
   1575       case 0x3E:
   1576          if ((regRs & 0x01) == 0) {
   1577             /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
   1578             DIP("dsrl32 r%u, r%u, %d", regRd, regRt, (Int)(sImmsa + 32));
   1579             assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
   1580             putIReg(regRd, mkexpr(tmpRd));
   1581          } else if ((regRs & 0x01) == 1) {
   1582             /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
   1583             DIP("drotr32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1584             vassert(mode64);
   1585             IRTemp tmpL = newTemp(ty);
   1586             IRTemp tmpR = newTemp(ty);
   1587             /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
   1588             assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
   1589             assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
   1590                               mkU8(63 - (uImmsa + 32))));
   1591             assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
   1592             assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
   1593             putIReg(regRd, mkexpr(tmpRd));
   1594          } else
   1595             return False;
   1596          break;
   1597 
   1598       case 0x16:
   1599          if ((uImmsa & 0x01) == 0) {
   1600             /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
   1601             DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
   1602             IRTemp tmpRs8 = newTemp(Ity_I8);
   1603             /* s = tmpRs[5..0] */
   1604             assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
   1605             assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
   1606             assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
   1607             putIReg(regRd, mkexpr(tmpRd));
   1608          } else if ((uImmsa & 0x01) == 1) {
   1609             /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
   1610             DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
   1611             IRTemp tmpL = newTemp(ty);
   1612             IRTemp tmpR = newTemp(ty);
   1613             IRTemp tmpRs8 = newTemp(Ity_I8);
   1614             IRTemp tmpLs8 = newTemp(Ity_I8);
   1615             IRTemp tmp64 = newTemp(ty);
   1616             /* s = tmpRs[5...0]
   1617                m = 64 - s
   1618                (tmpRt << s) | (tmpRt >> m) */
   1619 
   1620             assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
   1621             assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
   1622 
   1623             assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
   1624             assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
   1625 
   1626             assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
   1627             assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
   1628             assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
   1629             assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
   1630 
   1631             putIReg(regRd, mkexpr(tmpOr));
   1632          } else
   1633             return False;
   1634          break;
   1635 
   1636       case 0x38:  /* Doubleword Shift Left Logical - DSLL; MIPS64 */
   1637          DIP("dsll r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1638          vassert(mode64);
   1639          assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
   1640          putIReg(regRd, mkexpr(tmpRd));
   1641          break;
   1642 
   1643       case 0x3C:  /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
   1644          DIP("dsll32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1645          assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
   1646          putIReg(regRd, mkexpr(tmpRd));
   1647          break;
   1648 
   1649       case 0x14: {  /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
   1650          DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
   1651          IRTemp tmpRs8 = newTemp(Ity_I8);
   1652 
   1653          assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
   1654          assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
   1655          assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
   1656          putIReg(regRd, mkexpr(tmpRd));
   1657          break;
   1658       }
   1659 
   1660       case 0x3B:  /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
   1661          DIP("dsra r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1662          assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
   1663          putIReg(regRd, mkexpr(tmpRd));
   1664          break;
   1665 
   1666       case 0x3F:  /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
   1667                      MIPS64 */
   1668          DIP("dsra32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
   1669          assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
   1670          putIReg(regRd, mkexpr(tmpRd));
   1671          break;
   1672 
   1673       case 0x17: {  /* Doubleword Shift Right Arithmetic Variable - DSRAV;
   1674                        MIPS64 */
   1675          DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
   1676          IRTemp tmpRs8 = newTemp(Ity_I8);
   1677          assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
   1678          assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
   1679          assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
   1680          putIReg(regRd, mkexpr(tmpRd));
   1681          break;
   1682 
   1683       }
   1684 
   1685       default:
   1686          return False;
   1687 
   1688    }
   1689    return True;
   1690 }
   1691 
   1692 static IROp mkSzOp ( IRType ty, IROp op8 )
   1693 {
   1694    Int adj;
   1695    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
   1696    vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
   1697            || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
   1698            || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
   1699            || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
   1700    adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
   1701    return adj + op8;
   1702 }
   1703 
   1704 /*********************************************************/
   1705 /*---             Floating Point Compare              ---*/
   1706 /*********************************************************/
   1707 /* Function that returns a string that represent mips cond
   1708    mnemonic for the input code. */
   1709 static const HChar* showCondCode(UInt code) {
   1710    const HChar* ret;
   1711    switch (code) {
   1712       case 0: ret = "f"; break;
   1713       case 1: ret = "un"; break;
   1714       case 2: ret = "eq"; break;
   1715       case 3: ret = "ueq"; break;
   1716       case 4: ret = "olt"; break;
   1717       case 5: ret = "ult"; break;
   1718       case 6: ret = "ole"; break;
   1719       case 7: ret = "ule"; break;
   1720       case 8: ret = "sf"; break;
   1721       case 9: ret = "ngle"; break;
   1722       case 10: ret = "seq"; break;
   1723       case 11: ret = "ngl"; break;
   1724       case 12: ret = "lt"; break;
   1725       case 13: ret = "nge"; break;
   1726       case 14: ret = "le"; break;
   1727       case 15: ret = "ngt"; break;
   1728       default: vpanic("showCondCode"); break;
   1729    }
   1730    return ret;
   1731 }
   1732 
   1733 static Bool dis_instr_CCondFmt ( UInt cins )
   1734 {
   1735    IRTemp t0, t1, t2, t3, tmp5, tmp6;
   1736    IRTemp ccIR = newTemp(Ity_I32);
   1737    IRTemp ccMIPS = newTemp(Ity_I32);
   1738    UInt FC = get_FC(cins);
   1739    UInt fmt = get_fmt(cins);
   1740    UInt fs = get_fs(cins);
   1741    UInt ft = get_ft(cins);
   1742    UInt cond = get_cond(cins);
   1743 
   1744    if (FC == 0x3) {  /* C.cond.fmt */
   1745       UInt fpc_cc = get_fpc_cc(cins);
   1746       switch (fmt) {
   1747          case 0x10: {  /* C.cond.S */
   1748             DIP("c.%s.s %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
   1749             if (fp_mode64) {
   1750                t0 = newTemp(Ity_I32);
   1751                t1 = newTemp(Ity_I32);
   1752                t2 = newTemp(Ity_I32);
   1753                t3 = newTemp(Ity_I32);
   1754 
   1755                tmp5 = newTemp(Ity_F64);
   1756                tmp6 = newTemp(Ity_F64);
   1757 
   1758                assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
   1759                                  getFReg(fs))));
   1760                assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
   1761                                  getFReg(ft))));
   1762 
   1763                assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
   1764                putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
   1765                                    mkexpr(ccIR), True));
   1766                /* Map compare result from IR to MIPS
   1767                   FP cmp result | MIPS | IR
   1768                   --------------------------
   1769                   UN            | 0x1 | 0x45
   1770                   EQ            | 0x2 | 0x40
   1771                   GT            | 0x4 | 0x00
   1772                   LT            | 0x8 | 0x01
   1773                 */
   1774 
   1775                /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
   1776                assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
   1777                               binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
   1778                               binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)),
   1779                               binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
   1780                               binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
   1781                               mkU32(1))))));
   1782                putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
   1783                                    mkexpr(ccMIPS), True));
   1784 
   1785                /* UN */
   1786                assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
   1787                /* EQ */
   1788                assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1789                                                  mkU8(0x1)), mkU32(0x1)));
   1790                /* NGT */
   1791                assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
   1792                                  mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1)));
   1793                /* LT */
   1794                assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1795                                                  mkU8(0x3)), mkU32(0x1)));
   1796                switch (cond) {
   1797                   case 0x0:
   1798                      setFPUCondCode(mkU32(0), fpc_cc);
   1799                      break;
   1800                   case 0x1:
   1801                      setFPUCondCode(mkexpr(t0), fpc_cc);
   1802                      break;
   1803                   case 0x2:
   1804                      setFPUCondCode(mkexpr(t1), fpc_cc);
   1805                      break;
   1806                   case 0x3:
   1807                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1808                                           fpc_cc);
   1809                      break;
   1810                   case 0x4:
   1811                      setFPUCondCode(mkexpr(t3), fpc_cc);
   1812                      break;
   1813                   case 0x5:
   1814                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1815                                           fpc_cc);
   1816                      break;
   1817                   case 0x6:
   1818                      setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1819                                           fpc_cc);
   1820                      break;
   1821                   case 0x7:
   1822                      setFPUCondCode(mkexpr(t2), fpc_cc);
   1823                      break;
   1824                   case 0x8:
   1825                      setFPUCondCode(mkU32(0), fpc_cc);
   1826                      break;
   1827                   case 0x9:
   1828                      setFPUCondCode(mkexpr(t0), fpc_cc);
   1829                      break;
   1830                   case 0xA:
   1831                      setFPUCondCode(mkexpr(t1), fpc_cc);
   1832                      break;
   1833                   case 0xB:
   1834                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1835                                           fpc_cc);
   1836                      break;
   1837                   case 0xC:
   1838                      setFPUCondCode(mkexpr(t3), fpc_cc);
   1839                      break;
   1840                   case 0xD:
   1841                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1842                                           fpc_cc);
   1843                      break;
   1844                   case 0xE:
   1845                      setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1846                                           fpc_cc);
   1847                      break;
   1848                   case 0xF:
   1849                      setFPUCondCode(mkexpr(t2), fpc_cc);
   1850                      break;
   1851 
   1852                   default:
   1853                      return False;
   1854                }
   1855 
   1856             } else {
   1857                t0 = newTemp(Ity_I32);
   1858                t1 = newTemp(Ity_I32);
   1859                t2 = newTemp(Ity_I32);
   1860                t3 = newTemp(Ity_I32);
   1861 
   1862                assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
   1863                                   unop(Iop_F32toF64, getFReg(ft))));
   1864                /* Map compare result from IR to MIPS
   1865                   FP cmp result | MIPS | IR
   1866                   --------------------------
   1867                   UN            | 0x1 | 0x45
   1868                   EQ            | 0x2 | 0x40
   1869                   GT            | 0x4 | 0x00
   1870                   LT            | 0x8 | 0x01
   1871                 */
   1872 
   1873                /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
   1874                assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
   1875                               binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
   1876                               binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
   1877                                     mkU32(2)), binop(Iop_And32,
   1878                               binop(Iop_Xor32, mkexpr(ccIR),
   1879                               binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
   1880                               mkU32(1))))));
   1881                /* UN */
   1882                assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
   1883                /* EQ */
   1884                assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1885                       mkU8(0x1)), mkU32(0x1)));
   1886                /* NGT */
   1887                assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
   1888                       mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
   1889                /* LT */
   1890                assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1891                       mkU8(0x3)), mkU32(0x1)));
   1892 
   1893                switch (cond) {
   1894                   case 0x0:
   1895                      setFPUCondCode(mkU32(0), fpc_cc);
   1896                      break;
   1897                   case 0x1:
   1898                      setFPUCondCode(mkexpr(t0), fpc_cc);
   1899                      break;
   1900                   case 0x2:
   1901                      setFPUCondCode(mkexpr(t1), fpc_cc);
   1902                      break;
   1903                   case 0x3:
   1904                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1905                                           fpc_cc);
   1906                      break;
   1907                   case 0x4:
   1908                      setFPUCondCode(mkexpr(t3), fpc_cc);
   1909                      break;
   1910                   case 0x5:
   1911                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1912                                           fpc_cc);
   1913                      break;
   1914                   case 0x6:
   1915                      setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1916                                           fpc_cc);
   1917                      break;
   1918                   case 0x7:
   1919                      setFPUCondCode(mkexpr(t2), fpc_cc);
   1920                      break;
   1921                   case 0x8:
   1922                      setFPUCondCode(mkU32(0), fpc_cc);
   1923                      break;
   1924                   case 0x9:
   1925                      setFPUCondCode(mkexpr(t0), fpc_cc);
   1926                      break;
   1927                   case 0xA:
   1928                      setFPUCondCode(mkexpr(t1), fpc_cc);
   1929                      break;
   1930                   case 0xB:
   1931                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1932                                           fpc_cc);
   1933                      break;
   1934                   case 0xC:
   1935                      setFPUCondCode(mkexpr(t3), fpc_cc);
   1936                      break;
   1937                   case 0xD:
   1938                      setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1939                                           fpc_cc);
   1940                      break;
   1941                   case 0xE:
   1942                      setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1943                                           fpc_cc);
   1944                      break;
   1945                   case 0xF:
   1946                      setFPUCondCode(mkexpr(t2), fpc_cc);
   1947                      break;
   1948 
   1949                   default:
   1950                      return False;
   1951                }
   1952             }
   1953          }
   1954             break;
   1955 
   1956          case 0x11: {  /* C.cond.D */
   1957             DIP("c.%s.d %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
   1958             t0 = newTemp(Ity_I32);
   1959             t1 = newTemp(Ity_I32);
   1960             t2 = newTemp(Ity_I32);
   1961             t3 = newTemp(Ity_I32);
   1962             assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
   1963             /* Map compare result from IR to MIPS
   1964                FP cmp result | MIPS | IR
   1965                --------------------------
   1966                UN            | 0x1 | 0x45
   1967                EQ            | 0x2 | 0x40
   1968                GT            | 0x4 | 0x00
   1969                LT            | 0x8 | 0x01
   1970              */
   1971 
   1972             /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
   1973             assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
   1974                            binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
   1975                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
   1976                            binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
   1977                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
   1978                            mkU32(1))))));
   1979 
   1980             /* UN */
   1981             assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
   1982             /* EQ */
   1983             assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1984                    mkU8(0x1)), mkU32(0x1)));
   1985             /* NGT */
   1986             assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
   1987                    mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
   1988             /* LT */
   1989             assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1990                    mkU8(0x3)), mkU32(0x1)));
   1991 
   1992             switch (cond) {
   1993                case 0x0:
   1994                   setFPUCondCode(mkU32(0), fpc_cc);
   1995                   break;
   1996                case 0x1:
   1997                   setFPUCondCode(mkexpr(t0), fpc_cc);
   1998                   break;
   1999                case 0x2:
   2000                   setFPUCondCode(mkexpr(t1), fpc_cc);
   2001                   break;
   2002                case 0x3:
   2003                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   2004                                        fpc_cc);
   2005                   break;
   2006                case 0x4:
   2007                   setFPUCondCode(mkexpr(t3), fpc_cc);
   2008                   break;
   2009                case 0x5:
   2010                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   2011                                        fpc_cc);
   2012                   break;
   2013                case 0x6:
   2014                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   2015                                        fpc_cc);
   2016                   break;
   2017                case 0x7:
   2018                   setFPUCondCode(mkexpr(t2), fpc_cc);
   2019                   break;
   2020                case 0x8:
   2021                   setFPUCondCode(mkU32(0), fpc_cc);
   2022                   break;
   2023                case 0x9:
   2024                   setFPUCondCode(mkexpr(t0), fpc_cc);
   2025                   break;
   2026                case 0xA:
   2027                   setFPUCondCode(mkexpr(t1), fpc_cc);
   2028                   break;
   2029                case 0xB:
   2030                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   2031                                        fpc_cc);
   2032                   break;
   2033                case 0xC:
   2034                   setFPUCondCode(mkexpr(t3), fpc_cc);
   2035                   break;
   2036                case 0xD:
   2037                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   2038                                        fpc_cc);
   2039                   break;
   2040                case 0xE:
   2041                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   2042                                        fpc_cc);
   2043                   break;
   2044                case 0xF:
   2045                   setFPUCondCode(mkexpr(t2), fpc_cc);
   2046                   break;
   2047                default:
   2048                   return False;
   2049             }
   2050          }
   2051          break;
   2052 
   2053          default:
   2054             return False;
   2055       }
   2056    } else {
   2057       return False;
   2058    }
   2059 
   2060    return True;
   2061 }
   2062 
   2063 /*********************************************************/
   2064 /*---        Branch Instructions for mips64           ---*/
   2065 /*********************************************************/
   2066 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
   2067                                Bool(*resteerOkFn) (void *, Addr),
   2068                                void *callback_opaque, IRStmt ** set )
   2069 {
   2070    UInt jmpKind = 0;
   2071    UChar opc1 = get_opcode(theInstr);
   2072    UChar regRs = get_rs(theInstr);
   2073    UChar regRt = get_rt(theInstr);
   2074    UInt offset = get_imm(theInstr);
   2075    Long sOffset = extend_s_16to64(offset);
   2076    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2077    IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
   2078 
   2079    IRTemp tmp = newTemp(ty);
   2080    IRTemp tmpRs = newTemp(ty);
   2081    IRTemp tmpRt = newTemp(ty);
   2082    IRTemp tmpLt = newTemp(ty);
   2083    IRTemp tmpReg0 = newTemp(ty);
   2084 
   2085    UChar regLnk = 31;   /* reg 31 is link reg in MIPS */
   2086    Addr64 addrTgt = 0;
   2087    Addr64 cia = guest_PC_curr_instr;
   2088 
   2089    IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
   2090    IRExpr *eNia = mkSzImm(ty, cia + 8);
   2091    IRExpr *eCond = NULL;
   2092 
   2093    assign(tmpRs, getIReg(regRs));
   2094    assign(tmpRt, getIReg(regRt));
   2095    assign(tmpReg0, getIReg(0));
   2096 
   2097    eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
   2098 
   2099    switch (opc1) {
   2100       case 0x01:
   2101          switch (regRt) {
   2102             case 0x00: {  /* BLTZ rs, offset */
   2103                addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
   2104                IRTemp tmpLtRes = newTemp(Ity_I1);
   2105 
   2106                assign(tmp, eConst0);
   2107                assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
   2108                assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
   2109                       unop(Iop_1Uto32, mkexpr(tmpLtRes)));
   2110 
   2111                eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
   2112                              mkexpr(tmpReg0));
   2113 
   2114                jmpKind = Ijk_Boring;
   2115                break;
   2116             }
   2117 
   2118             case 0x01: {  /* BGEZ rs, offset */
   2119                IRTemp tmpLtRes = newTemp(Ity_I1);
   2120                addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
   2121 
   2122                assign(tmp, eConst0);
   2123                assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
   2124                assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
   2125                                       unop(Iop_1Uto32, mkexpr(tmpLtRes)));
   2126                eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
   2127                                     mkexpr(tmpReg0));
   2128 
   2129                jmpKind = Ijk_Boring;
   2130                break;
   2131             }
   2132 
   2133             case 0x11: {  /* BGEZAL rs, offset */
   2134                addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
   2135                putIReg(regLnk, eNia);
   2136                IRTemp tmpLtRes = newTemp(Ity_I1);
   2137 
   2138                assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
   2139                assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
   2140                                       unop(Iop_1Uto32, mkexpr(tmpLtRes)));
   2141 
   2142                eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
   2143                                     mkexpr(tmpReg0));
   2144 
   2145                jmpKind = Ijk_Call;
   2146                break;
   2147             }
   2148 
   2149             case 0x10: {  /* BLTZAL rs, offset */
   2150                IRTemp tmpLtRes = newTemp(Ity_I1);
   2151                IRTemp tmpRes = newTemp(ty);
   2152 
   2153                addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
   2154                putIReg(regLnk, eNia);
   2155 
   2156                assign(tmp, eConst0);
   2157                assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
   2158                assign(tmpRes, mode64 ? unop(Iop_1Uto64,
   2159                       mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
   2160                eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
   2161                                                      mkexpr(tmpReg0));
   2162 
   2163                jmpKind = Ijk_Call;
   2164                break;
   2165             }
   2166 
   2167          }
   2168          break;
   2169       default:
   2170          return False;
   2171       }
   2172    *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
   2173    return True;
   2174 }
   2175 
   2176 /*********************************************************/
   2177 /*---         Cavium Specific Instructions            ---*/
   2178 /*********************************************************/
   2179 
   2180 /* Convenience function to yield to thread scheduler */
   2181 static void jump_back(IRExpr *condition)
   2182 {
   2183    stmt( IRStmt_Exit(condition,
   2184                      Ijk_Yield,
   2185                      IRConst_U64( guest_PC_curr_instr ),
   2186                      OFFB_PC) );
   2187 }
   2188 
   2189 /* Based on s390_irgen_load_and_add32. */
   2190 static void mips_irgen_load_and_add32(IRTemp op1addr, IRTemp new_val,
   2191                                       UChar rd, Bool putIntoRd)
   2192 {
   2193    IRCAS *cas;
   2194    IRTemp old_mem = newTemp(Ity_I32);
   2195    IRTemp expd    = newTemp(Ity_I32);
   2196 
   2197    assign(expd, load(Ity_I32, mkexpr(op1addr)));
   2198 
   2199    cas = mkIRCAS(IRTemp_INVALID, old_mem,
   2200                  Iend_LE, mkexpr(op1addr),
   2201                  NULL, mkexpr(expd), /* expected value */
   2202                  NULL, mkexpr(new_val)  /* new value */);
   2203    stmt(IRStmt_CAS(cas));
   2204 
   2205    /* If old_mem contains the expected value, then the CAS succeeded.
   2206       Otherwise, it did not */
   2207    jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
   2208    if (putIntoRd)
   2209       putIReg(rd, mkWidenFrom32(Ity_I64, mkexpr(old_mem), True));
   2210 }
   2211 
   2212 /* Based on s390_irgen_load_and_add64. */
   2213 static void mips_irgen_load_and_add64(IRTemp op1addr, IRTemp new_val,
   2214                                       UChar rd, Bool putIntoRd)
   2215 {
   2216    IRCAS *cas;
   2217    IRTemp old_mem = newTemp(Ity_I64);
   2218    IRTemp expd    = newTemp(Ity_I64);
   2219 
   2220    assign(expd, load(Ity_I64, mkexpr(op1addr)));
   2221 
   2222    cas = mkIRCAS(IRTemp_INVALID, old_mem,
   2223                  Iend_LE, mkexpr(op1addr),
   2224                  NULL, mkexpr(expd), /* expected value */
   2225                  NULL, mkexpr(new_val)  /* new value */);
   2226    stmt(IRStmt_CAS(cas));
   2227 
   2228    /* If old_mem contains the expected value, then the CAS succeeded.
   2229       Otherwise, it did not */
   2230    jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
   2231    if (putIntoRd)
   2232       putIReg(rd, mkexpr(old_mem));
   2233 }
   2234 
   2235 static Bool dis_instr_CVM ( UInt theInstr )
   2236 {
   2237    UChar  opc2     = get_function(theInstr);
   2238    UChar  opc1     = get_opcode(theInstr);
   2239    UChar  regRs    = get_rs(theInstr);
   2240    UChar  regRt    = get_rt(theInstr);
   2241    UChar  regRd    = get_rd(theInstr);
   2242    /* MIPS trap instructions extract code from theInstr[15:6].
   2243       Cavium OCTEON instructions SNEI, SEQI extract immediate operands
   2244       from the same bit field [15:6]. */
   2245    UInt   imm      = get_code(theInstr);
   2246    UChar  lenM1    = get_msb(theInstr);
   2247    UChar  p        = get_lsb(theInstr);
   2248    IRType ty       = mode64? Ity_I64 : Ity_I32;
   2249    IRTemp tmp      = newTemp(ty);
   2250    IRTemp tmpRs    = newTemp(ty);
   2251    IRTemp tmpRt    = newTemp(ty);
   2252    IRTemp t1       = newTemp(ty);
   2253    UInt size;
   2254    assign(tmpRs, getIReg(regRs));
   2255 
   2256    switch(opc1) {
   2257       case 0x1C: {
   2258          switch(opc2) {
   2259             case 0x03: {  /* DMUL rd, rs, rt */
   2260                DIP("dmul r%d, r%d, r%d", regRd, regRs, regRt);
   2261                IRTemp t0 = newTemp(Ity_I128);
   2262                assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
   2263                putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
   2264                break;
   2265             }
   2266 
   2267             case 0x18: {  /* Store Atomic Add Word - SAA; Cavium OCTEON */
   2268                DIP("saa r%u, (r%u)", regRt, regRs);
   2269                IRTemp addr = newTemp(Ity_I64);
   2270                IRTemp new  = newTemp(Ity_I32);
   2271                assign (addr, getIReg(regRs));
   2272                assign(new, binop(Iop_Add32,
   2273                                  load(Ity_I32, mkexpr(addr)),
   2274                                  mkNarrowTo32(ty, getIReg(regRt))));
   2275                mips_irgen_load_and_add32(addr, new, 0, False);
   2276                break;
   2277             }
   2278 
   2279             /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
   2280             case 0x19: {
   2281                DIP( "saad r%u, (r%u)", regRt, regRs);
   2282                IRTemp addr = newTemp(Ity_I64);
   2283                IRTemp new  = newTemp(Ity_I64);
   2284                assign (addr, getIReg(regRs));
   2285                assign(new, binop(Iop_Add64,
   2286                                  load(Ity_I64, mkexpr(addr)),
   2287                                  getIReg(regRt)));
   2288                mips_irgen_load_and_add64(addr, new, 0, False);
   2289                break;
   2290             }
   2291 
   2292             /* LAI, LAID, LAD, LADD, LAS, LASD,
   2293                LAC, LACD, LAA, LAAD, LAW, LAWD */
   2294             case 0x1f: {
   2295                UInt opc3 = get_sa(theInstr);
   2296                IRTemp addr = newTemp(Ity_I64);
   2297                switch (opc3) {
   2298                   /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
   2299                   case 0x02: {
   2300                      DIP("lai r%u,(r%u)\n", regRd, regRs);
   2301                      IRTemp new  = newTemp(Ity_I32);
   2302                      assign(addr, getIReg(regRs));
   2303                      assign(new, binop(Iop_Add32,
   2304                                        load(Ity_I32, mkexpr(addr)),
   2305                                        mkU32(1)));
   2306                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2307                      break;
   2308                   }
   2309                   /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
   2310                   case 0x03: {
   2311                      DIP("laid r%u,(r%u)\n", regRd, regRs);
   2312                      IRTemp new  = newTemp(Ity_I64);
   2313                      assign(addr, getIReg(regRs));
   2314                      assign(new, binop(Iop_Add64,
   2315                                        load(Ity_I64, mkexpr(addr)),
   2316                                        mkU64(1)));
   2317                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2318                      break;
   2319                   }
   2320                   /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
   2321                   case 0x06: {
   2322                      DIP("lad r%u,(r%u)\n", regRd, regRs);
   2323                      IRTemp new  = newTemp(Ity_I32);
   2324                      assign(addr, getIReg(regRs));
   2325                      assign(new, binop(Iop_Sub32,
   2326                                        load(Ity_I32, mkexpr(addr)),
   2327                                        mkU32(1)));
   2328                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2329                      break;
   2330                   }
   2331                   /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
   2332                   case 0x07: {
   2333                      DIP("ladd r%u,(r%u)\n", regRd, regRs);
   2334                      IRTemp new  = newTemp(Ity_I64);
   2335                      assign (addr, getIReg(regRs));
   2336                      assign(new, binop(Iop_Sub64,
   2337                                        load(Ity_I64, mkexpr(addr)),
   2338                                        mkU64(1)));
   2339                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2340                      break;
   2341                   }
   2342                   /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
   2343                   case 0x0a: {
   2344                      DIP("las r%u,(r%u)\n", regRd, regRs);
   2345                      IRTemp new  = newTemp(Ity_I32);
   2346                      assign(addr, getIReg(regRs));
   2347                      assign(new, mkU32(0xffffffff));
   2348                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2349                      break;
   2350                   }
   2351                   /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
   2352                   case 0x0b: {
   2353                      DIP("lasd r%u,(r%u)\n", regRd, regRs);
   2354                      IRTemp new  = newTemp(Ity_I64);
   2355                      assign (addr, getIReg(regRs));
   2356                      assign(new, mkU64(0xffffffffffffffffULL));
   2357                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2358                      break;
   2359                   }
   2360                   /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
   2361                   case 0x0e: {
   2362                      DIP("lac r%u,(r%u)\n", regRd, regRs);
   2363                      IRTemp new  = newTemp(Ity_I32);
   2364                      assign (addr, getIReg(regRs));
   2365                      assign(new, mkU32(0));
   2366                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2367                      break;
   2368                   }
   2369                   /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
   2370                   case 0x0f: {
   2371                      DIP("lacd r%u,(r%u)\n", regRd, regRs);
   2372                      IRTemp new  = newTemp(Ity_I64);
   2373                      assign(addr, getIReg(regRs));
   2374                      assign(new, mkU64(0));
   2375                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2376                      break;
   2377                   }
   2378                   /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
   2379                   case 0x12: {
   2380                      DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
   2381                      IRTemp new  = newTemp(Ity_I32);
   2382                      assign(addr, getIReg(regRs));
   2383                      assign(new, binop(Iop_Add32,
   2384                                        load(Ity_I32, mkexpr(addr)),
   2385                                        mkNarrowTo32(ty, getIReg(regRt))));
   2386                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2387                      break;
   2388                   }
   2389                   /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
   2390                   case 0x13: {
   2391                      DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
   2392                      IRTemp new  = newTemp(Ity_I64);
   2393                      assign (addr, getIReg(regRs));
   2394                      assign(new, binop(Iop_Add64,
   2395                                        load(Ity_I64, mkexpr(addr)),
   2396                                        getIReg(regRt)));
   2397                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2398                      break;
   2399                   }
   2400                   /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
   2401                   case 0x16: {
   2402                      DIP("law r%u,(r%u)\n", regRd, regRs);
   2403                      IRTemp new  = newTemp(Ity_I32);
   2404                      assign(addr, getIReg(regRs));
   2405                      assign(new, mkNarrowTo32(ty, getIReg(regRt)));
   2406                      mips_irgen_load_and_add32(addr, new, regRd, True);
   2407                      break;
   2408                   }
   2409                   /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
   2410                   case 0x17: {
   2411                      DIP("lawd r%u,(r%u)\n", regRd, regRs);
   2412                      IRTemp new  = newTemp(Ity_I64);
   2413                      assign(addr, getIReg(regRs));
   2414                      assign(new, getIReg(regRt));
   2415                      mips_irgen_load_and_add64(addr, new, regRd, True);
   2416                      break;
   2417                   }
   2418                   default:
   2419                      vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
   2420                      vex_printf("Instruction=0x%08x\n", theInstr);
   2421                      return False;
   2422                }
   2423                break;
   2424             }
   2425 
   2426             /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
   2427             case 0x28: {
   2428                DIP("BADDU r%d, r%d, r%d", regRs, regRt, regRd);
   2429                IRTemp t0 = newTemp(Ity_I8);
   2430 
   2431                assign(t0, binop(Iop_Add8,
   2432                                 mkNarrowTo8(ty, getIReg(regRs)),
   2433                                 mkNarrowTo8(ty, getIReg(regRt))));
   2434 
   2435                if (mode64)
   2436                   putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
   2437                                        unop(Iop_8Uto64, mkexpr(t0)),
   2438                                        mkSzImm(ty, 0xFF)));
   2439                else
   2440                   putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
   2441                                        unop(Iop_8Uto32, mkexpr(t0)),
   2442                                        mkSzImm(ty, 0xFF)));
   2443                break;
   2444             }
   2445 
   2446             case 0x2c: {  /* Count Ones in a Word - POP; Cavium OCTEON */
   2447                int i, shift[5];
   2448                IRTemp mask[5];
   2449                IRTemp old = newTemp(ty);
   2450                IRTemp nyu = IRTemp_INVALID;
   2451                assign(old, getIReg(regRs));
   2452                DIP("pop r%d, r%d", regRd, regRs);
   2453 
   2454                for (i = 0; i < 5; i++) {
   2455                   mask[i] = newTemp(ty);
   2456                   shift[i] = 1 << i;
   2457                }
   2458                if(mode64) {
   2459                   assign(mask[0], mkU64(0x0000000055555555));
   2460                   assign(mask[1], mkU64(0x0000000033333333));
   2461                   assign(mask[2], mkU64(0x000000000F0F0F0F));
   2462                   assign(mask[3], mkU64(0x0000000000FF00FF));
   2463                   assign(mask[4], mkU64(0x000000000000FFFF));
   2464 
   2465                   for (i = 0; i < 5; i++) {
   2466                      nyu = newTemp(ty);
   2467                      assign(nyu,
   2468                             binop(Iop_Add64,
   2469                                   binop(Iop_And64,
   2470                                         mkexpr(old), mkexpr(mask[i])),
   2471                                   binop(Iop_And64,
   2472                                         binop(Iop_Shr64,
   2473                                               mkexpr(old), mkU8(shift[i])),
   2474                                         mkexpr(mask[i]))));
   2475                      old = nyu;
   2476                   }
   2477                } else {
   2478                   assign(mask[0], mkU32(0x55555555));
   2479                   assign(mask[1], mkU32(0x33333333));
   2480                   assign(mask[2], mkU32(0x0F0F0F0F));
   2481                   assign(mask[3], mkU32(0x00FF00FF));
   2482                   assign(mask[4], mkU32(0x0000FFFF));
   2483                   assign(old, getIReg(regRs));
   2484 
   2485                   for (i = 0; i < 5; i++) {
   2486                      nyu = newTemp(ty);
   2487                      assign(nyu,
   2488                             binop(Iop_Add32,
   2489                                   binop(Iop_And32,
   2490                                         mkexpr(old), mkexpr(mask[i])),
   2491                                   binop(Iop_And32,
   2492                                         binop(Iop_Shr32,
   2493                                               mkexpr(old), mkU8(shift[i])),
   2494                                         mkexpr(mask[i]))));
   2495                      old = nyu;
   2496                   }
   2497                }
   2498                putIReg(regRd, mkexpr(nyu));
   2499                break;
   2500             }
   2501 
   2502             /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
   2503             case 0x2d: {
   2504                int i, shift[6];
   2505                IRTemp mask[6];
   2506                IRTemp old = newTemp(ty);
   2507                IRTemp nyu = IRTemp_INVALID;
   2508                DIP("dpop r%d, r%d", regRd, regRs);
   2509 
   2510                for (i = 0; i < 6; i++) {
   2511                   mask[i] = newTemp(ty);
   2512                   shift[i] = 1 << i;
   2513                }
   2514                vassert(mode64); /*Caution! Only for Mode 64*/
   2515                assign(mask[0], mkU64(0x5555555555555555ULL));
   2516                assign(mask[1], mkU64(0x3333333333333333ULL));
   2517                assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
   2518                assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
   2519                assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
   2520                assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
   2521                assign(old, getIReg(regRs));
   2522                for (i = 0; i < 6; i++) {
   2523                   nyu = newTemp(Ity_I64);
   2524                   assign(nyu,
   2525                          binop(Iop_Add64,
   2526                                binop(Iop_And64,
   2527                                      mkexpr(old), mkexpr(mask[i])),
   2528                                binop(Iop_And64,
   2529                                      binop(Iop_Shr64,
   2530                                            mkexpr(old), mkU8(shift[i])),
   2531                                      mkexpr(mask[i]))));
   2532                   old = nyu;
   2533                }
   2534                putIReg(regRd, mkexpr(nyu));
   2535                break;
   2536             }
   2537 
   2538             case 0x32:  /* 5. CINS rd, rs, p, lenm1 */
   2539                DIP("cins r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
   2540                assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
   2541                                      mkU8(64-( lenM1+1 ))));
   2542                assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
   2543                                      mkU8(64-(p+lenM1+1))));
   2544                putIReg( regRt, mkexpr(tmpRt));
   2545                break;
   2546 
   2547             case 0x33:  /* 6. CINS32 rd, rs, p+32, lenm1 */
   2548                DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1);
   2549                assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
   2550                                      mkU8(64-( lenM1+1 ))));
   2551                assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
   2552                                      mkU8(32-(p+lenM1+1))));
   2553                putIReg( regRt, mkexpr(tmpRt));
   2554                break;
   2555 
   2556             case 0x3A:  /* 3. EXTS rt, rs, p len */
   2557                DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
   2558                size = lenM1 + 1;  /* lenm1+1 */
   2559                UChar lsAmt = 64 - (p + size);  /* p+lenm1+1 */
   2560                UChar rsAmt = 64 - size;  /* lenm1+1 */
   2561                tmp = newTemp(Ity_I64);
   2562                assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
   2563                putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
   2564                break;
   2565 
   2566             case 0x3B:  /* 4. EXTS32 rt, rs, p len */
   2567                DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
   2568                assign ( tmp  , binop(Iop_Shl64, mkexpr(tmpRs),
   2569                                      mkU8(32-(p+lenM1+1))));
   2570                assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
   2571                                      mkU8(64-(lenM1+1))) );
   2572                putIReg( regRt, mkexpr(tmpRt));
   2573                break;
   2574 
   2575             case 0x2B:  /* 20. SNE rd, rs, rt */
   2576                DIP("sne r%d, r%d, r%d", regRd,regRs, regRt);
   2577                if (mode64)
   2578                   putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
   2579                                                         getIReg(regRs),
   2580                                                         getIReg(regRt))));
   2581                else
   2582                   putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32,
   2583                                                        getIReg(regRs),
   2584                                                        getIReg(regRt))));
   2585                break;
   2586 
   2587             case 0x2A:  /* Set Equals - SEQ; Cavium OCTEON */
   2588                DIP("seq r%d, r%d, %d", regRd, regRs, regRt);
   2589                if (mode64)
   2590                   putIReg(regRd, unop(Iop_1Uto64,
   2591                                       binop(Iop_CmpEQ64, getIReg(regRs),
   2592                                             getIReg(regRt))));
   2593                else
   2594                   putIReg(regRd, unop(Iop_1Uto32,
   2595                                       binop(Iop_CmpEQ32, getIReg(regRs),
   2596                                             getIReg(regRt))));
   2597                break;
   2598 
   2599             case 0x2E:  /* Set Equals Immediate - SEQI; Cavium OCTEON */
   2600                DIP("seqi r%d, r%d, %d", regRt, regRs, imm);
   2601                if (mode64)
   2602                   putIReg(regRt, unop(Iop_1Uto64,
   2603                                       binop(Iop_CmpEQ64, getIReg(regRs),
   2604                                             mkU64(extend_s_10to64(imm)))));
   2605                else
   2606                   putIReg(regRt, unop(Iop_1Uto32,
   2607                                       binop(Iop_CmpEQ32, getIReg(regRs),
   2608                                             mkU32(extend_s_10to32(imm)))));
   2609                break;
   2610 
   2611             case 0x2F:  /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
   2612                DIP("snei r%d, r%d, %d", regRt, regRs, imm);
   2613                if (mode64)
   2614                   putIReg(regRt, unop(Iop_1Uto64,
   2615                                    binop(Iop_CmpNE64,
   2616                                          getIReg(regRs),
   2617                                          mkU64(extend_s_10to64(imm)))));
   2618                else
   2619                   putIReg(regRt, unop(Iop_1Uto32,
   2620                                    binop(Iop_CmpNE32,
   2621                                          getIReg(regRs),
   2622                                          mkU32(extend_s_10to32(imm)))));
   2623                break;
   2624 
   2625             default:
   2626                return False;
   2627          }
   2628          break;
   2629       } /* opc1 0x1C ends here*/
   2630       case 0x1F: {
   2631          switch(opc2) {
   2632             case 0x0A: {  // lx - Load indexed instructions
   2633                switch (get_sa(theInstr)) {
   2634                   case 0x00: {  // LWX rd, index(base)
   2635                      DIP("lwx r%d, r%d(r%d)", regRd, regRt, regRs);
   2636                      LOADX_STORE_PATTERN;
   2637                      putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
   2638                                                   True));
   2639                      break;
   2640                   }
   2641                   case 0x08: {  // LDX rd, index(base)
   2642                      DIP("ldx r%d, r%d(r%d)", regRd, regRt, regRs);
   2643                      vassert(mode64); /* Currently Implemented only for n64 */
   2644                      LOADX_STORE_PATTERN;
   2645                      putIReg(regRd, load(Ity_I64, mkexpr(t1)));
   2646                      break;
   2647                   }
   2648                   case 0x06: {  // LBUX rd, index(base)
   2649                      DIP("lbux r%d, r%d(r%d)", regRd, regRt, regRs);
   2650                      LOADX_STORE_PATTERN;
   2651                      if (mode64)
   2652                         putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
   2653                                                              mkexpr(t1))));
   2654                      else
   2655                         putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
   2656                                                              mkexpr(t1))));
   2657                      break;
   2658                   }
   2659                   case 0x10: {  // LWUX rd, index(base) (Cavium OCTEON)
   2660                      DIP("lwux r%d, r%d(r%d)", regRd, regRt, regRs);
   2661                      LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
   2662                      putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
   2663                                                   False));
   2664                      break;
   2665                   }
   2666                   case 0x14: {  // LHUX rd, index(base) (Cavium OCTEON)
   2667                      DIP("lhux r%d, r%d(r%d)", regRd, regRt, regRs);
   2668                      LOADX_STORE_PATTERN;
   2669                      if (mode64)
   2670                         putIReg(regRd,
   2671                                 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
   2672                      else
   2673                         putIReg(regRd,
   2674                                 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
   2675                      break;
   2676                   }
   2677                   case 0x16: {  // LBX rd, index(base) (Cavium OCTEON)
   2678                      DIP("lbx r%d, r%d(r%d)", regRd, regRs, regRt);
   2679                      LOADX_STORE_PATTERN;
   2680                      if (mode64)
   2681                         putIReg(regRd,
   2682                                 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
   2683                      else
   2684                         putIReg(regRd,
   2685                                 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
   2686                      break;
   2687                   }
   2688                   default:
   2689                      vex_printf("\nUnhandled LX instruction opc3 = %x\n",
   2690                                 get_sa(theInstr));
   2691                      return False;
   2692                }
   2693                break;
   2694             }
   2695          } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
   2696          break;
   2697       } /* opc1 = 0x1F ends here*/
   2698       default:
   2699          return False;
   2700    } /* main opc1 switch ends here */
   2701    return True;
   2702 }
   2703 
   2704 /*------------------------------------------------------------*/
   2705 /*---       Disassemble a single DSP ASE instruction       ---*/
   2706 /*------------------------------------------------------------*/
   2707 
   2708 static UInt disDSPInstr_MIPS_WRK ( UInt cins )
   2709 {
   2710    IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
   2711           t15, t16, t17;
   2712    UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
   2713         wrdsp_mask, dsp_imm, shift;
   2714 
   2715    opcode = get_opcode(cins);
   2716    rs = get_rs(cins);
   2717    rt = get_rt(cins);
   2718    rd = get_rd(cins);
   2719    sa = get_sa(cins);
   2720    function = get_function(cins);
   2721    ac = get_acNo(cins);
   2722    ac_mfhilo = get_acNo_mfhilo(cins);
   2723    rddsp_mask = get_rddspMask(cins);
   2724    wrdsp_mask = get_wrdspMask(cins);
   2725    dsp_imm = get_dspImm(cins);
   2726    shift = get_shift(cins);
   2727 
   2728    switch (opcode) {
   2729       case 0x00: {  /* Special */
   2730          switch (function) {
   2731             case 0x10: {  /* MFHI */
   2732                DIP("mfhi ac%d r%d", ac_mfhilo, rd);
   2733                putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
   2734                break;
   2735             }
   2736 
   2737             case 0x11: {  /* MTHI */
   2738                DIP("mthi ac%d r%d", ac, rs);
   2739                t1 = newTemp(Ity_I32);
   2740                assign(t1, unop(Iop_64to32, getAcc(ac)));
   2741                putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
   2742                break;
   2743             }
   2744 
   2745             case 0x12: {  /* MFLO */
   2746                DIP("mflo ac%d r%d", ac_mfhilo, rd);
   2747                putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
   2748                break;
   2749             }
   2750 
   2751             case 0x13: {  /* MTLO */
   2752                DIP("mtlo ac%d r%d", ac, rs);
   2753                t1 = newTemp(Ity_I32);
   2754                assign(t1, unop(Iop_64HIto32, getAcc(ac)));
   2755                putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
   2756                break;
   2757             }
   2758 
   2759             case 0x18: {  /* MULT */
   2760                DIP("mult ac%d r%d, r%d", ac, rs, rt);
   2761                t1 = newTemp(Ity_I64);
   2762                assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
   2763                                 mkNarrowTo32(Ity_I32, getIReg(rt))));
   2764                putAcc(ac, mkexpr(t1));
   2765                break;
   2766             }
   2767 
   2768             case 0x19: {  /* MULTU */
   2769                DIP("multu ac%d r%d, r%d", ac, rs, rt);
   2770                t1 = newTemp(Ity_I64);
   2771                assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
   2772                                              mkNarrowTo32(Ity_I32,
   2773                                                           getIReg(rt))));
   2774                putAcc(ac, mkexpr(t1));
   2775             break;
   2776             }
   2777          }
   2778          break;
   2779       }
   2780       case 0x1C: {  /* Special2 */
   2781          switch (function) {
   2782             case 0x00: {  /* MADD */
   2783                DIP("madd ac%d, r%d, r%d", ac, rs, rt);
   2784                t1 = newTemp(Ity_I64);
   2785                t2 = newTemp(Ity_I64);
   2786                t3 = newTemp(Ity_I64);
   2787 
   2788                assign(t1, getAcc(ac));
   2789                assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
   2790                assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
   2791 
   2792                putAcc(ac, mkexpr(t3));
   2793                break;
   2794             }
   2795             case 0x01: {  /* MADDU */
   2796                DIP("maddu ac%d r%d, r%d", ac, rs, rt);
   2797                t1 = newTemp(Ity_I64);
   2798                t2 = newTemp(Ity_I64);
   2799                t3 = newTemp(Ity_I64);
   2800 
   2801                assign(t1, getAcc(ac));
   2802                assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
   2803                assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
   2804 
   2805                putAcc(ac, mkexpr(t3));
   2806                break;
   2807             }
   2808             case 0x04: {  /* MSUB */
   2809                DIP("msub ac%d r%d, r%d", ac, rs, rt);
   2810                t1 = newTemp(Ity_I64);
   2811                t2 = newTemp(Ity_I64);
   2812                t3 = newTemp(Ity_I64);
   2813 
   2814                assign(t1, getAcc(ac));
   2815                assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
   2816                assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
   2817 
   2818                putAcc(ac, mkexpr(t3));
   2819                break;
   2820             }
   2821             case 0x05: {  /* MSUBU */
   2822                DIP("msubu ac%d r%d, r%d", ac, rs, rt);
   2823                t1 = newTemp(Ity_I64);
   2824                t2 = newTemp(Ity_I64);
   2825                t3 = newTemp(Ity_I64);
   2826 
   2827                assign(t1, getAcc(ac));
   2828                assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
   2829                assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
   2830 
   2831                putAcc(ac, mkexpr(t3));
   2832                break;
   2833             }
   2834          }
   2835          break;
   2836       }
   2837       case 0x1F: {  /* Special3 */
   2838          switch (function) {
   2839             case 0x12: {  /* ABSQ_S.PH */
   2840                switch (sa) {
   2841                   case 0x1: {  /* ABSQ_S.QB */
   2842                      DIP("absq_s.qb r%d, r%d", rd, rt);
   2843                      vassert(!mode64);
   2844                      t0 = newTemp(Ity_I8);
   2845                      t1 = newTemp(Ity_I1);
   2846                      t2 = newTemp(Ity_I1);
   2847                      t3 = newTemp(Ity_I8);
   2848                      t4 = newTemp(Ity_I8);
   2849                      t5 = newTemp(Ity_I1);
   2850                      t6 = newTemp(Ity_I1);
   2851                      t7 = newTemp(Ity_I8);
   2852                      t8 = newTemp(Ity_I8);
   2853                      t9 = newTemp(Ity_I1);
   2854                      t10 = newTemp(Ity_I1);
   2855                      t11 = newTemp(Ity_I8);
   2856                      t12 = newTemp(Ity_I8);
   2857                      t13 = newTemp(Ity_I1);
   2858                      t14 = newTemp(Ity_I1);
   2859                      t15 = newTemp(Ity_I8);
   2860                      t16 = newTemp(Ity_I32);
   2861                      t17 = newTemp(Ity_I32);
   2862 
   2863                      /* Absolute value of the rightmost byte (bits 7-0). */
   2864                      /* t0 - rightmost byte. */
   2865                      assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
   2866                      /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
   2867                      assign(t1, binop(Iop_CmpEQ32,
   2868                                       unop(Iop_8Uto32, mkexpr(t0)),
   2869                                       mkU32(0x00000080)));
   2870                      /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
   2871                      assign(t2, unop(Iop_32to1,
   2872                                      binop(Iop_Shr32,
   2873                                            binop(Iop_And32,
   2874                                                  getIReg(rt),
   2875                                                  mkU32(0x00000080)),
   2876                                            mkU8(0x7))));
   2877                      /* t3 holds abs(t0). */
   2878                      assign(t3, IRExpr_ITE(mkexpr(t1),
   2879                                            mkU8(0x7F),
   2880                                            IRExpr_ITE(mkexpr(t2),
   2881                                                       binop(Iop_Add8,
   2882                                                             unop(Iop_Not8,
   2883                                                                  mkexpr(t0)),
   2884                                                             mkU8(0x1)),
   2885                                                       mkexpr(t0))));
   2886 
   2887                      /* Absolute value of bits 15-8. */
   2888                      /* t4 - input byte. */
   2889                      assign(t4,
   2890                             unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
   2891                      /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
   2892                      assign(t5, binop(Iop_CmpEQ32,
   2893                                       unop(Iop_8Uto32, mkexpr(t4)),
   2894                                       mkU32(0x00000080)));
   2895                      /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
   2896                      assign(t6, unop(Iop_32to1,
   2897                                      binop(Iop_Shr32,
   2898                                            binop(Iop_And32,
   2899                                                  getIReg(rt),
   2900                                                  mkU32(0x00008000)),
   2901                                            mkU8(15))));
   2902                      /* t3 holds abs(t4). */
   2903                      assign(t7, IRExpr_ITE(mkexpr(t5),
   2904                                            mkU8(0x7F),
   2905                                            IRExpr_ITE(mkexpr(t6),
   2906                                                       binop(Iop_Add8,
   2907                                                             unop(Iop_Not8,
   2908                                                                  mkexpr(t4)),
   2909                                                             mkU8(0x1)),
   2910                                                       mkexpr(t4))));
   2911 
   2912                      /* Absolute value of bits 23-15. */
   2913                      /* t8 - input byte. */
   2914                      assign(t8,
   2915                             unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
   2916                      /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
   2917                      assign(t9, binop(Iop_CmpEQ32,
   2918                                       unop(Iop_8Uto32, mkexpr(t8)),
   2919                                       mkU32(0x00000080)));
   2920                      /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
   2921                      assign(t10, unop(Iop_32to1,
   2922                                       binop(Iop_Shr32,
   2923                                             binop(Iop_And32,
   2924                                                   getIReg(rt),
   2925                                                   mkU32(0x00800000)),
   2926                                             mkU8(23))));
   2927                      /* t3 holds abs(t8). */
   2928                      assign(t11, IRExpr_ITE(mkexpr(t9),
   2929                                             mkU8(0x7F),
   2930                                             IRExpr_ITE(mkexpr(t10),
   2931                                                        binop(Iop_Add8,
   2932                                                              unop(Iop_Not8,
   2933                                                                   mkexpr(t8)),
   2934                                                              mkU8(0x1)),
   2935                                                        mkexpr(t8))));
   2936 
   2937                      /* Absolute value of bits 31-24. */
   2938                      /* t12 - input byte. */
   2939                      assign(t12,
   2940                             unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
   2941                      /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
   2942                      assign(t13, binop(Iop_CmpEQ32,
   2943                                        unop(Iop_8Uto32, mkexpr(t12)),
   2944                                        mkU32(0x00000080)));
   2945                      /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
   2946                      assign(t14, unop(Iop_32to1,
   2947                                       binop(Iop_Shr32,
   2948                                             binop(Iop_And32,
   2949                                                   getIReg(rt),
   2950                                                   mkU32(0x80000000)),
   2951                                             mkU8(31))));
   2952                      /* t15 holds abs(t12). */
   2953                      assign(t15, IRExpr_ITE(mkexpr(t13),
   2954                                             mkU8(0x7F),
   2955                                             IRExpr_ITE(mkexpr(t14),
   2956                                                        binop(Iop_Add8,
   2957                                                              unop(Iop_Not8,
   2958                                                                   mkexpr(t12)),
   2959                                                              mkU8(0x1)),
   2960                                                        mkexpr(t12))));
   2961 
   2962                      /* t16 holds !0 if any of input bytes is 0x80 or 0
   2963                         otherwise. */
   2964                      assign(t16,
   2965                             binop(Iop_Or32,
   2966                                   binop(Iop_Or32,
   2967                                         binop(Iop_Or32,
   2968                                               unop(Iop_1Sto32, mkexpr(t13)),
   2969                                               unop(Iop_1Sto32, mkexpr(t9))),
   2970                                         unop(Iop_1Sto32, mkexpr(t5))),
   2971                                   unop(Iop_1Sto32, mkexpr(t1))));
   2972 
   2973                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   2974                                                     mkexpr(t16),
   2975                                                     mkU32(0x0)),
   2976                                               getDSPControl(),
   2977                                               binop(Iop_Or32,
   2978                                                     getDSPControl(),
   2979                                                     mkU32(0x00100000))));
   2980 
   2981                      /* t17 = t15|t11|t7|t3 */
   2982                      assign(t17,
   2983                             binop(Iop_16HLto32,
   2984                                   binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
   2985                                   binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
   2986 
   2987                      putIReg(rd, mkexpr(t17));
   2988                      break;
   2989                   }
   2990                   case 0x2: {  /* REPL.QB */
   2991                      DIP("repl.qb r%d, %d", rd, dsp_imm);
   2992                      vassert(!mode64);
   2993 
   2994                      putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
   2995                                        (dsp_imm << 8) | (dsp_imm)));
   2996                      break;
   2997                   }
   2998                   case 0x3: {  /* REPLV.QB */
   2999                      DIP("replv.qb r%d, r%d", rd, rt);
   3000                      vassert(!mode64);
   3001                      t0 = newTemp(Ity_I8);
   3002 
   3003                      assign(t0, unop(Iop_32to8,
   3004                                 binop(Iop_And32, getIReg(rt), mkU32(0xff))));
   3005                      putIReg(rd,
   3006                              binop(Iop_16HLto32,
   3007                                    binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
   3008                                    binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
   3009                      break;
   3010                   }
   3011                   case 0x4: {  /* PRECEQU.PH.QBL */
   3012                      DIP("precequ.ph.qbl r%d, r%d", rd, rt);
   3013                      vassert(!mode64);
   3014 
   3015                      putIReg(rd, binop(Iop_Or32,
   3016                                        binop(Iop_Shr32,
   3017                                              binop(Iop_And32,
   3018                                                    getIReg(rt),
   3019                                                    mkU32(0xff000000)),
   3020                                              mkU8(1)),
   3021                                        binop(Iop_Shr32,
   3022                                              binop(Iop_And32,
   3023                                                    getIReg(rt),
   3024                                                    mkU32(0x00ff0000)),
   3025                                              mkU8(9))));
   3026                      break;
   3027                   }
   3028                   case 0x5: {  /* PRECEQU.PH.QBR */
   3029                      DIP("precequ.ph.qbr r%d, r%d", rd, rt);
   3030                      vassert(!mode64);
   3031 
   3032                      putIReg(rd, binop(Iop_Or32,
   3033                                        binop(Iop_Shl32,
   3034                                              binop(Iop_And32,
   3035                                                    getIReg(rt),
   3036                                                    mkU32(0x0000ff00)),
   3037                                              mkU8(15)),
   3038                                        binop(Iop_Shl32,
   3039                                              binop(Iop_And32,
   3040                                                    getIReg(rt),
   3041                                                    mkU32(0x000000ff)),
   3042                                              mkU8(7))));
   3043                      break;
   3044                   }
   3045                   case 0x6: {  /* PRECEQU.PH.QBLA */
   3046                      DIP("precequ.ph.qbla r%d, r%d", rd, rt);
   3047                      vassert(!mode64);
   3048 
   3049                      putIReg(rd, binop(Iop_Or32,
   3050                                        binop(Iop_Shr32,
   3051                                              binop(Iop_And32,
   3052                                                    getIReg(rt),
   3053                                                    mkU32(0xff000000)),
   3054                                              mkU8(1)),
   3055                                        binop(Iop_Shr32,
   3056                                              binop(Iop_And32,
   3057                                                    getIReg(rt),
   3058                                                    mkU32(0x0000ff00)),
   3059                                              mkU8(1))));
   3060                      break;
   3061                   }
   3062                   case 0x7: {  /* PRECEQU.PH.QBRA */
   3063                      DIP("precequ.ph.qbra r%d, r%d", rd, rt);
   3064                      vassert(!mode64);
   3065 
   3066                      putIReg(rd, binop(Iop_Or32,
   3067                                        binop(Iop_Shl32,
   3068                                              binop(Iop_And32,
   3069                                                    getIReg(rt),
   3070                                                    mkU32(0x00ff0000)),
   3071                                              mkU8(7)),
   3072                                        binop(Iop_Shl32,
   3073                                              binop(Iop_And32,
   3074                                                    getIReg(rt),
   3075                                                    mkU32(0x000000ff)),
   3076                                              mkU8(7))));
   3077                      break;
   3078                   }
   3079                   case 0x9: {  /* ABSQ_S.PH */
   3080                      DIP("absq_s.ph r%d, r%d", rd, rt);
   3081                      vassert(!mode64);
   3082                      t0 = newTemp(Ity_I16);
   3083                      t1 = newTemp(Ity_I1);
   3084                      t2 = newTemp(Ity_I1);
   3085                      t3 = newTemp(Ity_I16);
   3086                      t4 = newTemp(Ity_I16);
   3087                      t5 = newTemp(Ity_I1);
   3088                      t6 = newTemp(Ity_I1);
   3089                      t7 = newTemp(Ity_I16);
   3090                      t8 = newTemp(Ity_I32);
   3091                      t9 = newTemp(Ity_I32);
   3092 
   3093                      /* t0 holds lower 16 bits of value in rt. */
   3094                      assign(t0, unop(Iop_32to16, getIReg(rt)));
   3095                      /* t1 holds 1 if t0 is equal to 0x8000. */
   3096                      assign(t1, binop(Iop_CmpEQ32,
   3097                                       unop(Iop_16Uto32, mkexpr(t0)),
   3098                                       mkU32(0x00008000)));
   3099                      /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
   3100                      assign(t2, unop(Iop_32to1,
   3101                                      binop(Iop_Shr32,
   3102                                            binop(Iop_And32,
   3103                                                  getIReg(rt),
   3104                                                  mkU32(0x00008000)),
   3105                                            mkU8(15))));
   3106                      /* t3 holds abs(t0). */
   3107                      assign(t3, IRExpr_ITE(mkexpr(t1),
   3108                                            mkU16(0x7FFF),
   3109                                            IRExpr_ITE(mkexpr(t2),
   3110                                                       binop(Iop_Add16,
   3111                                                             unop(Iop_Not16,
   3112                                                                  mkexpr(t0)),
   3113                                                             mkU16(0x1)),
   3114                                                       mkexpr(t0))));
   3115 
   3116                      /* t4 holds lower 16 bits of value in rt. */
   3117                      assign(t4, unop(Iop_32HIto16, getIReg(rt)));
   3118                      /* t5 holds 1 if t4 is equal to 0x8000. */
   3119                      assign(t5, binop(Iop_CmpEQ32,
   3120                                       unop(Iop_16Uto32, mkexpr(t4)),
   3121                                       mkU32(0x00008000)));
   3122                      /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
   3123                      assign(t6, unop(Iop_32to1,
   3124                                      binop(Iop_Shr32,
   3125                                            binop(Iop_And32,
   3126                                                  getIReg(rt),
   3127                                                  mkU32(0x80000000)),
   3128                                            mkU8(31))));
   3129                      /* t7 holds abs(t4). */
   3130                      assign(t7, IRExpr_ITE(mkexpr(t5),
   3131                                            mkU16(0x7FFF),
   3132                                            IRExpr_ITE(mkexpr(t6),
   3133                                                       binop(Iop_Add16,
   3134                                                             unop(Iop_Not16,
   3135                                                                  mkexpr(t4)),
   3136                                                             mkU16(0x1)),
   3137                                                       mkexpr(t4))));
   3138                      /* If any of the two input halfwords is equal 0x8000,
   3139                         set bit 20 in DSPControl register. */
   3140                      assign(t8, binop(Iop_Or32,
   3141                                       unop(Iop_1Sto32, mkexpr(t5)),
   3142                                       unop(Iop_1Sto32, mkexpr(t1))));
   3143 
   3144                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   3145                                                     mkexpr(t8),
   3146                                                     mkU32(0x0)),
   3147                                               getDSPControl(),
   3148                                               binop(Iop_Or32,
   3149                                                     getDSPControl(),
   3150                                                     mkU32(0x00100000))));
   3151 
   3152                      /* t9 = t7|t3 */
   3153                      assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
   3154 
   3155                      putIReg(rd, mkexpr(t9));
   3156                      break;
   3157                   }
   3158                   case 0xA: {  /* REPL.PH */
   3159                      DIP("repl.ph r%d, %d", rd, dsp_imm);
   3160                      vassert(!mode64);
   3161                      UShort immediate = extend_s_10to16(dsp_imm);
   3162 
   3163                      putIReg(rd, mkU32(immediate << 16 | immediate));
   3164                      break;
   3165                   }
   3166                   case 0xB: {  /* REPLV.PH */
   3167                      DIP("replv.ph r%d, r%d", rd, rt);
   3168                      vassert(!mode64);
   3169 
   3170                      putIReg(rd, binop(Iop_16HLto32,
   3171                                        unop(Iop_32to16, getIReg(rt)),
   3172                                        unop(Iop_32to16, getIReg(rt))));
   3173                      break;
   3174                   }
   3175                   case 0xC: {  /* PRECEQ.W.PHL */
   3176                      DIP("preceq.w.phl r%d, r%d", rd, rt);
   3177                      vassert(!mode64);
   3178                      putIReg(rd, binop(Iop_And32,
   3179                                        getIReg(rt),
   3180                                        mkU32(0xffff0000)));
   3181                      break;
   3182                   }
   3183                   case 0xD: {  /* PRECEQ.W.PHR */
   3184                      DIP("preceq.w.phr r%d, r%d", rd, rt);
   3185                      vassert(!mode64);
   3186                      putIReg(rd, binop(Iop_16HLto32,
   3187                                        unop(Iop_32to16, getIReg(rt)),
   3188                                        mkU16(0x0)));
   3189                      break;
   3190                   }
   3191                   case 0x11: {  /* ABSQ_S.W */
   3192                      DIP("absq_s.w r%d, r%d", rd, rt);
   3193                      vassert(!mode64);
   3194                      t0 = newTemp(Ity_I1);
   3195                      t1 = newTemp(Ity_I1);
   3196                      t2 = newTemp(Ity_I32);
   3197 
   3198                      assign(t0,
   3199                             binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
   3200 
   3201                      putDSPControl(IRExpr_ITE(mkexpr(t0),
   3202                                               binop(Iop_Or32,
   3203                                                     getDSPControl(),
   3204                                                     mkU32(0x00100000)),
   3205                                               getDSPControl()));
   3206 
   3207                      assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
   3208 
   3209                      assign(t2, IRExpr_ITE(mkexpr(t0),
   3210                                            mkU32(0x7FFFFFFF),
   3211                                            IRExpr_ITE(mkexpr(t1),
   3212                                                       binop(Iop_Add32,
   3213                                                             unop(Iop_Not32,
   3214                                                                  getIReg(rt)),
   3215                                                             mkU32(0x1)),
   3216                                                       getIReg(rt))));
   3217                      putIReg(rd, mkexpr(t2));
   3218                      break;
   3219                   }
   3220                   case 0x1B: {  /* BITREV */
   3221                      DIP("bitrev r%d, r%d", rd, rt);
   3222                      vassert(!mode64);
   3223                      /* 32bit reversal as seen on Bit Twiddling Hacks site
   3224                         http://graphics.stanford.edu/~seander/bithacks.html
   3225                         section ReverseParallel */
   3226                      t1 = newTemp(Ity_I32);
   3227                      t2 = newTemp(Ity_I32);
   3228                      t3 = newTemp(Ity_I32);
   3229                      t4 = newTemp(Ity_I32);
   3230                      t5 = newTemp(Ity_I32);
   3231 
   3232                      assign(t1, binop(Iop_Or32,
   3233                                       binop(Iop_Shr32,
   3234                                             binop(Iop_And32,
   3235                                                   getIReg(rt),
   3236                                                   mkU32(0xaaaaaaaa)),
   3237                                             mkU8(0x1)),
   3238                                       binop(Iop_Shl32,
   3239                                             binop(Iop_And32,
   3240                                                   getIReg(rt),
   3241                                                   mkU32(0x55555555)),
   3242                                             mkU8(0x1))));
   3243                      assign(t2, binop(Iop_Or32,
   3244                                       binop(Iop_Shr32,
   3245                                             binop(Iop_And32,
   3246                                                   mkexpr(t1),
   3247                                                   mkU32(0xcccccccc)),
   3248                                             mkU8(0x2)),
   3249                                       binop(Iop_Shl32,
   3250                                             binop(Iop_And32,
   3251                                                   mkexpr(t1),
   3252                                                   mkU32(0x33333333)),
   3253                                             mkU8(0x2))));
   3254                      assign(t3, binop(Iop_Or32,
   3255                                       binop(Iop_Shr32,
   3256                                             binop(Iop_And32,
   3257                                                   mkexpr(t2),
   3258                                                   mkU32(0xf0f0f0f0)),
   3259                                             mkU8(0x4)),
   3260                                       binop(Iop_Shl32,
   3261                                             binop(Iop_And32,
   3262                                                   mkexpr(t2),
   3263                                                   mkU32(0x0f0f0f0f)),
   3264                                             mkU8(0x4))));
   3265                      assign(t4, binop(Iop_Or32,
   3266                                       binop(Iop_Shr32,
   3267                                             binop(Iop_And32,
   3268                                                   mkexpr(t3),
   3269                                                   mkU32(0xff00ff00)),
   3270                                             mkU8(0x8)),
   3271                                       binop(Iop_Shl32,
   3272                                             binop(Iop_And32,
   3273                                                   mkexpr(t3),
   3274                                                   mkU32(0x00ff00ff)),
   3275                                             mkU8(0x8))));
   3276                      assign(t5, binop(Iop_Or32,
   3277                                       binop(Iop_Shr32,
   3278                                             mkexpr(t4),
   3279                                             mkU8(0x10)),
   3280                                       binop(Iop_Shl32,
   3281                                             mkexpr(t4),
   3282                                             mkU8(0x10))));
   3283                      putIReg(rd, binop(Iop_Shr32,
   3284                                        mkexpr(t5),
   3285                                        mkU8(16)));
   3286                      break;
   3287                   }
   3288                   case 0x1C: {  /* PRECEU.PH.QBL */
   3289                      DIP("preceu.ph.qbl r%d, r%d", rd, rt);
   3290                      vassert(!mode64);
   3291 
   3292                      putIReg(rd, binop(Iop_Or32,
   3293                                        binop(Iop_Shr32,
   3294                                              binop(Iop_And32,
   3295                                                    getIReg(rt),
   3296                                                    mkU32(0xff000000)),
   3297                                              mkU8(8)),
   3298                                        binop(Iop_Shr32,
   3299                                              binop(Iop_And32,
   3300                                                    getIReg(rt),
   3301                                                    mkU32(0x00ff0000)),
   3302                                              mkU8(16))));
   3303                      break;
   3304                   }
   3305                   case 0x1E: {  /* PRECEU.PH.QBLA */
   3306                      DIP("preceu.ph.qbla r%d, r%d", rd, rt);
   3307                      vassert(!mode64);
   3308 
   3309                      putIReg(rd, binop(Iop_Or32,
   3310                                        binop(Iop_Shr32,
   3311                                              binop(Iop_And32,
   3312                                                    getIReg(rt),
   3313                                                    mkU32(0xff000000)),
   3314                                              mkU8(8)),
   3315                                        binop(Iop_Shr32,
   3316                                              binop(Iop_And32,
   3317                                                    getIReg(rt),
   3318                                                    mkU32(0x0000ff00)),
   3319                                              mkU8(8))));
   3320                      break;
   3321                   }
   3322                   case 0x1D: {  /* PRECEU.PH.QBR */
   3323                      DIP("preceu.ph.qbr r%d, r%d", rd, rt);
   3324                      vassert(!mode64);
   3325 
   3326                      putIReg(rd, binop(Iop_Or32,
   3327                                        binop(Iop_Shl32,
   3328                                              binop(Iop_And32,
   3329                                                    getIReg(rt),
   3330                                                    mkU32(0x0000ff00)),
   3331                                              mkU8(8)),
   3332                                        binop(Iop_And32,
   3333                                              getIReg(rt),
   3334                                              mkU32(0x000000ff))));
   3335                      break;
   3336                   }
   3337                   case 0x1F: {  /* PRECEU.PH.QBRA */
   3338                      DIP("preceu.ph.qbra r%d, r%d", rd, rt);
   3339                      vassert(!mode64);
   3340 
   3341                      putIReg(rd, binop(Iop_Or32,
   3342                                        binop(Iop_And32,
   3343                                              getIReg(rt),
   3344                                              mkU32(0x00ff0000)),
   3345                                        binop(Iop_And32,
   3346                                              getIReg(rt),
   3347                                              mkU32(0x000000ff))));
   3348                      break;
   3349                   }
   3350                   default:
   3351                      return -1;
   3352                }
   3353                break;  /* end of ABSQ_S.PH */
   3354             }
   3355             case 0x38: {  /* EXTR.W */
   3356                switch(sa) {
   3357                   case 0x0: {  /* EXTR.W */
   3358                      DIP("extr.w r%d, ac%d, %d", rt, ac, rs);
   3359                      vassert(!mode64);
   3360                      t0 = newTemp(Ity_I64);
   3361                      t1 = newTemp(Ity_I64);
   3362                      t2 = newTemp(Ity_I32);
   3363                      t3 = newTemp(Ity_I1);
   3364                      t4 = newTemp(Ity_I1);
   3365                      t5 = newTemp(Ity_I1);
   3366                      t6 = newTemp(Ity_I1);
   3367                      t7 = newTemp(Ity_I32);
   3368                      t8 = newTemp(Ity_I64);
   3369                      t9 = newTemp(Ity_I64);
   3370                      t10 = newTemp(Ity_I1);
   3371                      t11 = newTemp(Ity_I1);
   3372                      t12 = newTemp(Ity_I1);
   3373                      t13 = newTemp(Ity_I1);
   3374                      t14 = newTemp(Ity_I32);
   3375 
   3376                      assign(t0, getAcc(ac));
   3377                      if (0 == rs) {
   3378                         assign(t1, mkexpr(t0));
   3379                      } else {
   3380                         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
   3381                      }
   3382                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   3383                      assign(t3, binop(Iop_CmpNE32,
   3384                                       unop(Iop_64HIto32,
   3385                                            mkexpr(t1)),
   3386                                       mkU32(0)));
   3387                      assign(t4, binop(Iop_CmpNE32,
   3388                                       binop(Iop_And32,
   3389                                             unop(Iop_64to32,
   3390                                                  mkexpr(t1)),
   3391                                             mkU32(0x80000000)),
   3392                                       mkU32(0)));
   3393                      /* Check if bits 63..31 of the result in t1 aren't
   3394                         0x1ffffffff. */
   3395                      assign(t5, binop(Iop_CmpNE32,
   3396                                       unop(Iop_64HIto32,
   3397                                            mkexpr(t1)),
   3398                                       mkU32(0xffffffff)));
   3399                      assign(t6, binop(Iop_CmpNE32,
   3400                                       binop(Iop_And32,
   3401                                             unop(Iop_64to32,
   3402                                                  mkexpr(t1)),
   3403                                             mkU32(0x80000000)),
   3404                                       mkU32(0x80000000)));
   3405                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   3406                         control register. */
   3407                      assign(t7, binop(Iop_And32,
   3408                                       binop(Iop_Or32,
   3409                                             unop(Iop_1Sto32, mkexpr(t3)),
   3410                                             unop(Iop_1Sto32, mkexpr(t4))),
   3411                                       binop(Iop_Or32,
   3412                                             unop(Iop_1Sto32, mkexpr(t5)),
   3413                                             unop(Iop_1Sto32, mkexpr(t6)))));
   3414                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3415                                                     mkexpr(t7),
   3416                                                     mkU32(0)),
   3417                                               binop(Iop_Or32,
   3418                                                     getDSPControl(),
   3419                                                     mkU32(0x00800000)),
   3420                                               getDSPControl()));
   3421 
   3422                      /* If the last discarded bit is 1, there would be carry
   3423                         when rounding, otherwise there wouldn't. We use that
   3424                         fact and just add the value of the last discarded bit
   3425                         to the least sifgnificant bit of the shifted value
   3426                         from acc. */
   3427                      if (0 == rs) {
   3428                         assign(t8, mkU64(0x0ULL));
   3429                      } else {
   3430                         assign(t8, binop(Iop_And64,
   3431                                          binop(Iop_Shr64,
   3432                                                mkexpr(t0),
   3433                                                mkU8(rs-1)),
   3434                                          mkU64(0x1ULL)));
   3435                      }
   3436                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   3437 
   3438                      /* Repeat previous steps for the rounded value. */
   3439                      assign(t10, binop(Iop_CmpNE32,
   3440                                       unop(Iop_64HIto32,
   3441                                            mkexpr(t9)),
   3442                                       mkU32(0)));
   3443                      assign(t11, binop(Iop_CmpNE32,
   3444                                       binop(Iop_And32,
   3445                                             unop(Iop_64to32,
   3446                                                  mkexpr(t9)),
   3447                                             mkU32(0x80000000)),
   3448                                       mkU32(0)));
   3449 
   3450                      assign(t12, binop(Iop_CmpNE32,
   3451                                       unop(Iop_64HIto32,
   3452                                            mkexpr(t9)),
   3453                                       mkU32(0xffffffff)));
   3454                      assign(t13, binop(Iop_CmpNE32,
   3455                                       binop(Iop_And32,
   3456                                             unop(Iop_64to32,
   3457                                                  mkexpr(t9)),
   3458                                             mkU32(0x80000000)),
   3459                                       mkU32(0x80000000)));
   3460 
   3461                      assign(t14, binop(Iop_And32,
   3462                                       binop(Iop_Or32,
   3463                                             unop(Iop_1Sto32, mkexpr(t10)),
   3464                                             unop(Iop_1Sto32, mkexpr(t11))),
   3465                                       binop(Iop_Or32,
   3466                                             unop(Iop_1Sto32, mkexpr(t12)),
   3467                                             unop(Iop_1Sto32, mkexpr(t13)))));
   3468                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3469                                                     mkexpr(t14),
   3470                                                     mkU32(0)),
   3471                                               binop(Iop_Or32,
   3472                                                     getDSPControl(),
   3473                                                     mkU32(0x00800000)),
   3474                                               getDSPControl()));
   3475                      if (0 == rs) {
   3476                         putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
   3477                      } else {
   3478                         putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
   3479                      }
   3480                      break;
   3481                   }
   3482                   case 0x1: {  /* EXTRV.W */
   3483                      DIP("extrv.w r%d, ac%d, r%d", rt, ac, rs);
   3484                      vassert(!mode64);
   3485                      t0 = newTemp(Ity_I64);
   3486                      t1 = newTemp(Ity_I64);
   3487                      t2 = newTemp(Ity_I32);
   3488                      t3 = newTemp(Ity_I1);
   3489                      t4 = newTemp(Ity_I1);
   3490                      t5 = newTemp(Ity_I1);
   3491                      t6 = newTemp(Ity_I1);
   3492                      t7 = newTemp(Ity_I32);
   3493                      t8 = newTemp(Ity_I64);
   3494                      t9 = newTemp(Ity_I64);
   3495                      t10 = newTemp(Ity_I1);
   3496                      t11 = newTemp(Ity_I1);
   3497                      t12 = newTemp(Ity_I1);
   3498                      t13 = newTemp(Ity_I1);
   3499                      t14 = newTemp(Ity_I32);
   3500                      t15 = newTemp(Ity_I8);
   3501 
   3502                      assign(t15, unop(Iop_32to8,
   3503                                       binop(Iop_And32,
   3504                                             getIReg(rs),
   3505                                             mkU32(0x1f))));
   3506                      assign(t0, getAcc(ac));
   3507                      assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
   3508                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
   3509                                                         unop(Iop_8Uto32,
   3510                                                              mkexpr(t15)),
   3511                                                         mkU32(0)),
   3512                                                   unop(Iop_64to32, mkexpr(t0)),
   3513                                                   unop(Iop_64to32, mkexpr(t1))));
   3514 
   3515                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   3516                      assign(t3, binop(Iop_CmpNE32,
   3517                                       unop(Iop_64HIto32,
   3518                                            mkexpr(t1)),
   3519                                       mkU32(0)));
   3520                      assign(t4, binop(Iop_CmpNE32,
   3521                                       binop(Iop_And32,
   3522                                             unop(Iop_64to32,
   3523                                                  mkexpr(t1)),
   3524                                             mkU32(0x80000000)),
   3525                                       mkU32(0)));
   3526                      /* Check if bits 63..31 of the result in t1 aren't
   3527                         0x1ffffffff. */
   3528                      assign(t5, binop(Iop_CmpNE32,
   3529                                       unop(Iop_64HIto32,
   3530                                            mkexpr(t1)),
   3531                                       mkU32(0xffffffff)));
   3532                      assign(t6, binop(Iop_CmpNE32,
   3533                                       binop(Iop_And32,
   3534                                             unop(Iop_64to32,
   3535                                                  mkexpr(t1)),
   3536                                             mkU32(0x80000000)),
   3537                                       mkU32(0x80000000)));
   3538                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   3539                         control register. */
   3540                      assign(t7, binop(Iop_And32,
   3541                                       binop(Iop_Or32,
   3542                                             unop(Iop_1Sto32, mkexpr(t3)),
   3543                                             unop(Iop_1Sto32, mkexpr(t4))),
   3544                                       binop(Iop_Or32,
   3545                                             unop(Iop_1Sto32, mkexpr(t5)),
   3546                                             unop(Iop_1Sto32, mkexpr(t6)))));
   3547                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3548                                                     mkexpr(t7),
   3549                                                     mkU32(0)),
   3550                                               binop(Iop_Or32,
   3551                                                     getDSPControl(),
   3552                                                     mkU32(0x00800000)),
   3553                                               getDSPControl()));
   3554 
   3555                      /* If the last discarded bit is 1, there would be carry
   3556                         when rounding, otherwise there wouldn't. We use that
   3557                         fact and just add the value of the last discarded bit
   3558                         to the least sifgnificant bit of the shifted value
   3559                         from acc. */
   3560                      assign(t8,
   3561                             IRExpr_ITE(binop(Iop_CmpEQ32,
   3562                                              unop(Iop_8Uto32,
   3563                                                   mkexpr(t15)),
   3564                                              mkU32(0)),
   3565                                        mkU64(0x0ULL),
   3566                                        binop(Iop_And64,
   3567                                              binop(Iop_Shr64,
   3568                                                    mkexpr(t0),
   3569                                                    unop(Iop_32to8,
   3570                                                         binop(Iop_Sub32,
   3571                                                               unop(Iop_8Uto32,
   3572                                                                    mkexpr(t15)),
   3573                                                                    mkU32(1)))),
   3574                                              mkU64(0x1ULL))));
   3575 
   3576                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   3577 
   3578                      /* Repeat previous steps for the rounded value. */
   3579                      assign(t10, binop(Iop_CmpNE32,
   3580                                       unop(Iop_64HIto32,
   3581                                            mkexpr(t9)),
   3582                                       mkU32(0)));
   3583                      assign(t11, binop(Iop_CmpNE32,
   3584                                       binop(Iop_And32,
   3585                                             unop(Iop_64to32,
   3586                                                  mkexpr(t9)),
   3587                                             mkU32(0x80000000)),
   3588                                       mkU32(0)));
   3589 
   3590                      assign(t12, binop(Iop_CmpNE32,
   3591                                       unop(Iop_64HIto32,
   3592                                            mkexpr(t9)),
   3593                                       mkU32(0xffffffff)));
   3594                      assign(t13, binop(Iop_CmpNE32,
   3595                                       binop(Iop_And32,
   3596                                             unop(Iop_64to32,
   3597                                                  mkexpr(t9)),
   3598                                             mkU32(0x80000000)),
   3599                                       mkU32(0x80000000)));
   3600 
   3601                      assign(t14, binop(Iop_And32,
   3602                                       binop(Iop_Or32,
   3603                                             unop(Iop_1Sto32, mkexpr(t10)),
   3604                                             unop(Iop_1Sto32, mkexpr(t11))),
   3605                                       binop(Iop_Or32,
   3606                                             unop(Iop_1Sto32, mkexpr(t12)),
   3607                                             unop(Iop_1Sto32, mkexpr(t13)))));
   3608                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3609                                                     mkexpr(t14),
   3610                                                     mkU32(0)),
   3611                                               binop(Iop_Or32,
   3612                                                     getDSPControl(),
   3613                                                     mkU32(0x00800000)),
   3614                                               getDSPControl()));
   3615                      break;
   3616                   }
   3617                   case 0x2: {  /* EXTP */
   3618                      DIP("extp r%d, ac%d, %d", rt, ac, rs);
   3619                      vassert(!mode64);
   3620                      t0 = newTemp(Ity_I64);
   3621                      t1 = newTemp(Ity_I32);
   3622                      t2 = newTemp(Ity_I1);
   3623                      t3 = newTemp(Ity_I1);
   3624                      t4 = newTemp(Ity_I8);
   3625                      t5 = newTemp(Ity_I64);
   3626                      t6 = newTemp(Ity_I64);
   3627                      t7 = newTemp(Ity_I32);
   3628 
   3629                      assign(t0, getAcc(ac));
   3630                      /* Extract pos field of DSPControl register. */
   3631                      assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   3632 
   3633                      /* Check if (pos - size) >= 0 [size <= pos]
   3634                         if (pos < size)
   3635                            put 1 to EFI field of DSPControl register
   3636                         else
   3637                            extract bits from acc and put 0 to EFI field of
   3638                            DSPCtrl */
   3639                      assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
   3640 
   3641                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   3642                                               binop(Iop_Or32,
   3643                                                     binop(Iop_And32,
   3644                                                           getDSPControl(),
   3645                                                           mkU32(0xffffbfff)),
   3646                                                     mkU32(0x4000)),
   3647                                               binop(Iop_And32,
   3648                                                     getDSPControl(),
   3649                                                     mkU32(0xffffbfff))));
   3650 
   3651                      /* If pos <= 31, shift right the value from the acc
   3652                         (pos-size) times and take (size+1) bits from the least
   3653                         significant positions. Otherwise, shift left the value
   3654                         (63-pos) times, take (size+1) bits from the most
   3655                         significant positions and shift right (31-size) times.*/
   3656                      assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
   3657 
   3658                      assign(t4,
   3659                            IRExpr_ITE(mkexpr(t3),
   3660                                       unop(Iop_32to8,
   3661                                            binop(Iop_Sub32,
   3662                                                  mkexpr(t1), mkU32(rs))),
   3663                                       unop(Iop_32to8,
   3664                                            binop(Iop_Sub32,
   3665                                                  mkU32(63), mkexpr(t1)))));
   3666 
   3667                      assign(t5, IRExpr_ITE(mkexpr(t3),
   3668                                            binop(Iop_Shr64,
   3669                                                  mkexpr(t0), mkexpr(t4)),
   3670                                            binop(Iop_Shl64,
   3671                                                  mkexpr(t0), mkexpr(t4))));
   3672 
   3673                      /* t6 holds a mask for bit extraction */
   3674                      assign(t6,
   3675                             IRExpr_ITE(mkexpr(t3),
   3676                                        unop(Iop_Not64,
   3677                                             binop(Iop_Shl64,
   3678                                                   mkU64(0xffffffffffffffffULL),
   3679                                                   mkU8(rs+1))),
   3680                                        unop(Iop_Not64,
   3681                                             binop(Iop_Shr64,
   3682                                                   mkU64(0xffffffffffffffffULL),
   3683                                                   mkU8(rs+1)))));
   3684 
   3685                      assign(t7, IRExpr_ITE(mkexpr(t3),
   3686                                            unop(Iop_64to32,
   3687                                                 binop(Iop_And64,
   3688                                                       mkexpr(t5),
   3689                                                       mkexpr(t6))),
   3690                                            binop(Iop_Shr32,
   3691                                                  unop(Iop_64HIto32,
   3692                                                       binop(Iop_And64,
   3693                                                             mkexpr(t5),
   3694                                                             mkexpr(t6))),
   3695                                                  mkU8(31-rs))));
   3696 
   3697                      putIReg(rt, mkexpr(t7));
   3698                      break;
   3699                   }
   3700                   case 0x3: {  /* EXTPV */
   3701                      DIP("extpv r%d, ac%d, r%d", rt, ac, rs);
   3702                      vassert(!mode64);
   3703                      t0 = newTemp(Ity_I64);
   3704                      t1 = newTemp(Ity_I32);
   3705                      t2 = newTemp(Ity_I1);
   3706                      t3 = newTemp(Ity_I1);
   3707                      t4 = newTemp(Ity_I8);
   3708                      t5 = newTemp(Ity_I64);
   3709                      t6 = newTemp(Ity_I64);
   3710                      t7 = newTemp(Ity_I32);
   3711                      t8 = newTemp(Ity_I32);
   3712 
   3713                      assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
   3714                      assign(t0, getAcc(ac));
   3715                      /* Extract pos field of DSPControl register. */
   3716                      assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   3717 
   3718                      /* Check if (pos - size) >= 0 [size <= pos]
   3719                         if (pos < size)
   3720                            put 1 to EFI field of DSPControl register
   3721                         else
   3722                            extract bits from acc and put 0 to EFI field of
   3723                            DSPCtrl */
   3724                      assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
   3725 
   3726                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   3727                                               binop(Iop_Or32,
   3728                                                     binop(Iop_And32,
   3729                                                           getDSPControl(),
   3730                                                           mkU32(0xffffbfff)),
   3731                                                     mkU32(0x4000)),
   3732                                               binop(Iop_And32,
   3733                                                     getDSPControl(),
   3734                                                     mkU32(0xffffbfff))));
   3735 
   3736                      /* If pos <= 31, shift right the value from the acc
   3737                         (pos-size) times and take (size+1) bits from the least
   3738                         significant positions. Otherwise, shift left the value
   3739                         (63-pos) times, take (size+1) bits from the most
   3740                         significant positions and shift right (31-size)
   3741                         times. */
   3742                      assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
   3743 
   3744                      assign(t4,
   3745                            IRExpr_ITE(mkexpr(t3),
   3746                                       unop(Iop_32to8,
   3747                                            binop(Iop_Sub32,
   3748                                                  mkexpr(t1), mkexpr(t8))),
   3749                                       unop(Iop_32to8,
   3750                                            binop(Iop_Sub32,
   3751                                                  mkU32(63), mkexpr(t1)))));
   3752 
   3753                      assign(t5, IRExpr_ITE(mkexpr(t3),
   3754                                            binop(Iop_Shr64,
   3755                                                  mkexpr(t0), mkexpr(t4)),
   3756                                            binop(Iop_Shl64,
   3757                                                  mkexpr(t0), mkexpr(t4))));
   3758 
   3759                      /* t6 holds a mask for bit extraction. */
   3760                      assign(t6,
   3761                             IRExpr_ITE(mkexpr(t3),
   3762                                        unop(Iop_Not64,
   3763                                             binop(Iop_Shl64,
   3764                                                   mkU64(0xffffffffffffffffULL),
   3765                                                   unop(Iop_32to8,
   3766                                                        binop(Iop_Add32,
   3767                                                              mkexpr(t8),
   3768                                                              mkU32(1))))),
   3769                                        unop(Iop_Not64,
   3770                                             binop(Iop_Shr64,
   3771                                                   mkU64(0xffffffffffffffffULL),
   3772                                                   unop(Iop_32to8,
   3773                                                        binop(Iop_Add32,
   3774                                                              mkexpr(t8),
   3775                                                              mkU32(1)))))));
   3776 
   3777                      assign(t7, IRExpr_ITE(mkexpr(t3),
   3778                                            unop(Iop_64to32,
   3779                                                 binop(Iop_And64,
   3780                                                       mkexpr(t5),
   3781                                                       mkexpr(t6))),
   3782                                            binop(Iop_Shr32,
   3783                                                  unop(Iop_64HIto32,
   3784                                                       binop(Iop_And64,
   3785                                                             mkexpr(t5),
   3786                                                             mkexpr(t6))),
   3787                                                  unop(Iop_32to8,
   3788                                                       binop(Iop_Sub32,
   3789                                                             mkU32(31),
   3790                                                             mkexpr(t8))))));
   3791 
   3792                      putIReg(rt, mkexpr(t7));
   3793                      break;
   3794                   }
   3795                   case 0x4: {  /* EXTR_R.W */
   3796                      DIP("extr_r.w r%d, ac%d, %d", rt, ac, rs);
   3797                      vassert(!mode64);
   3798                      t0 = newTemp(Ity_I64);
   3799                      t1 = newTemp(Ity_I64);
   3800                      t2 = newTemp(Ity_I32);
   3801                      t3 = newTemp(Ity_I1);
   3802                      t4 = newTemp(Ity_I1);
   3803                      t5 = newTemp(Ity_I1);
   3804                      t6 = newTemp(Ity_I1);
   3805                      t7 = newTemp(Ity_I32);
   3806                      t8 = newTemp(Ity_I64);
   3807                      t9 = newTemp(Ity_I64);
   3808                      t10 = newTemp(Ity_I1);
   3809                      t11 = newTemp(Ity_I1);
   3810                      t12 = newTemp(Ity_I1);
   3811                      t13 = newTemp(Ity_I1);
   3812                      t14 = newTemp(Ity_I32);
   3813                      t15 = newTemp(Ity_I64);
   3814                      t16 = newTemp(Ity_I1);
   3815 
   3816                      assign(t0, getAcc(ac));
   3817                      assign(t16, binop(Iop_CmpEQ32,
   3818                                        mkU32(rs),
   3819                                        mkU32(0)));
   3820                      assign(t1, IRExpr_ITE(mkexpr(t16),
   3821                                            mkexpr(t0),
   3822                                            binop(Iop_Sar64,
   3823                                                  mkexpr(t0),
   3824                                                  mkU8(rs))));
   3825                      /* If the last discarded bit is 1, there would be carry
   3826                         when rounding, otherwise there wouldn't. We use that
   3827                         fact and just add the value of the last discarded bit
   3828                         to the least significant bit of the shifted value
   3829                         from acc. */
   3830                      assign(t15, binop(Iop_Shr64,
   3831                                        mkexpr(t0),
   3832                                        unop(Iop_32to8,
   3833                                             binop(Iop_Sub32,
   3834                                                   binop(Iop_And32,
   3835                                                         mkU32(rs),
   3836                                                         mkU32(0x1f)),
   3837                                                   mkU32(1)))));
   3838 
   3839                      assign(t8,
   3840                             IRExpr_ITE(mkexpr(t16),
   3841                                        mkU64(0x0ULL),
   3842                                        binop(Iop_And64,
   3843                                              mkexpr(t15),
   3844                                              mkU64(0x0000000000000001ULL))));
   3845                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   3846                      putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
   3847 
   3848                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   3849                      assign(t3, binop(Iop_CmpNE32,
   3850                                       unop(Iop_64HIto32,
   3851                                            mkexpr(t1)),
   3852                                       mkU32(0)));
   3853                      assign(t4, binop(Iop_CmpNE32,
   3854                                       binop(Iop_And32,
   3855                                             unop(Iop_64to32,
   3856                                                  mkexpr(t1)),
   3857                                             mkU32(0x80000000)),
   3858                                       mkU32(0)));
   3859 
   3860                      /* Check if bits 63..31 of the result in t1 aren't
   3861                         0x1ffffffff. */
   3862                      assign(t5, binop(Iop_CmpNE32,
   3863                                       unop(Iop_64HIto32,
   3864                                            mkexpr(t1)),
   3865                                       mkU32(0xffffffff)));
   3866                      assign(t6, binop(Iop_CmpNE32,
   3867                                       binop(Iop_And32,
   3868                                             unop(Iop_64to32,
   3869                                                  mkexpr(t1)),
   3870                                             mkU32(0x80000000)),
   3871                                       mkU32(0x80000000)));
   3872                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   3873                         control register. */
   3874                      assign(t7, binop(Iop_And32,
   3875                                       binop(Iop_Or32,
   3876                                             unop(Iop_1Sto32, mkexpr(t3)),
   3877                                             unop(Iop_1Sto32, mkexpr(t4))),
   3878                                       binop(Iop_Or32,
   3879                                             unop(Iop_1Sto32, mkexpr(t5)),
   3880                                             unop(Iop_1Sto32, mkexpr(t6)))));
   3881                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3882                                                     mkexpr(t7),
   3883                                                     mkU32(0)),
   3884                                               binop(Iop_Or32,
   3885                                                     getDSPControl(),
   3886                                                     mkU32(0x00800000)),
   3887                                               getDSPControl()));
   3888 
   3889                      /* Repeat previous steps for the rounded value. */
   3890                      assign(t10, binop(Iop_CmpNE32,
   3891                                       unop(Iop_64HIto32,
   3892                                            mkexpr(t9)),
   3893                                       mkU32(0)));
   3894                      assign(t11, binop(Iop_CmpNE32,
   3895                                       binop(Iop_And32,
   3896                                             unop(Iop_64to32,
   3897                                                  mkexpr(t9)),
   3898                                             mkU32(0x80000000)),
   3899                                       mkU32(0)));
   3900 
   3901                      assign(t12, binop(Iop_CmpNE32,
   3902                                       unop(Iop_64HIto32,
   3903                                            mkexpr(t9)),
   3904                                       mkU32(0xffffffff)));
   3905                      assign(t13, binop(Iop_CmpNE32,
   3906                                       binop(Iop_And32,
   3907                                             unop(Iop_64to32,
   3908                                                  mkexpr(t9)),
   3909                                             mkU32(0x80000000)),
   3910                                       mkU32(0x80000000)));
   3911 
   3912                      assign(t14, binop(Iop_And32,
   3913                                       binop(Iop_Or32,
   3914                                             unop(Iop_1Sto32, mkexpr(t10)),
   3915                                             unop(Iop_1Sto32, mkexpr(t11))),
   3916                                       binop(Iop_Or32,
   3917                                             unop(Iop_1Sto32, mkexpr(t12)),
   3918                                             unop(Iop_1Sto32, mkexpr(t13)))));
   3919                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3920                                                     mkexpr(t14),
   3921                                                     mkU32(0)),
   3922                                               binop(Iop_Or32,
   3923                                                     getDSPControl(),
   3924                                                     mkU32(0x00800000)),
   3925                                               getDSPControl()));
   3926                      break;
   3927                   }
   3928                   case 0x5: {  /* EXTRV_R.W */
   3929                      DIP("extrv_r.w r%d, ac%d, r%d", rt, ac, rs);
   3930                      vassert(!mode64);
   3931                      t0 = newTemp(Ity_I64);
   3932                      t1 = newTemp(Ity_I64);
   3933                      t2 = newTemp(Ity_I32);
   3934                      t3 = newTemp(Ity_I1);
   3935                      t4 = newTemp(Ity_I1);
   3936                      t5 = newTemp(Ity_I1);
   3937                      t6 = newTemp(Ity_I1);
   3938                      t7 = newTemp(Ity_I32);
   3939                      t8 = newTemp(Ity_I64);
   3940                      t9 = newTemp(Ity_I64);
   3941                      t10 = newTemp(Ity_I1);
   3942                      t11 = newTemp(Ity_I1);
   3943                      t12 = newTemp(Ity_I1);
   3944                      t13 = newTemp(Ity_I1);
   3945                      t14 = newTemp(Ity_I32);
   3946                      t15 = newTemp(Ity_I8);
   3947 
   3948                      assign(t15, unop(Iop_32to8,
   3949                                       binop(Iop_And32,
   3950                                             getIReg(rs),
   3951                                             mkU32(0x1f))));
   3952                      assign(t0, getAcc(ac));
   3953                      assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
   3954 
   3955                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   3956                      assign(t3, binop(Iop_CmpNE32,
   3957                                       unop(Iop_64HIto32,
   3958                                            mkexpr(t1)),
   3959                                       mkU32(0)));
   3960                      assign(t4, binop(Iop_CmpNE32,
   3961                                       binop(Iop_And32,
   3962                                             unop(Iop_64to32,
   3963                                                  mkexpr(t1)),
   3964                                             mkU32(0x80000000)),
   3965                                       mkU32(0)));
   3966                      /* Check if bits 63..31 of the result in t1 aren't
   3967                         0x1ffffffff. */
   3968                      assign(t5, binop(Iop_CmpNE32,
   3969                                       unop(Iop_64HIto32,
   3970                                            mkexpr(t1)),
   3971                                       mkU32(0xffffffff)));
   3972                      assign(t6, binop(Iop_CmpNE32,
   3973                                       binop(Iop_And32,
   3974                                             unop(Iop_64to32,
   3975                                                  mkexpr(t1)),
   3976                                             mkU32(0x80000000)),
   3977                                       mkU32(0x80000000)));
   3978                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   3979                         control register. */
   3980                      assign(t7, binop(Iop_And32,
   3981                                       binop(Iop_Or32,
   3982                                             unop(Iop_1Sto32, mkexpr(t3)),
   3983                                             unop(Iop_1Sto32, mkexpr(t4))),
   3984                                       binop(Iop_Or32,
   3985                                             unop(Iop_1Sto32, mkexpr(t5)),
   3986                                             unop(Iop_1Sto32, mkexpr(t6)))));
   3987                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   3988                                                     mkexpr(t7),
   3989                                                     mkU32(0)),
   3990                                               binop(Iop_Or32,
   3991                                                     getDSPControl(),
   3992                                                     mkU32(0x00800000)),
   3993                                               getDSPControl()));
   3994 
   3995                      /* If the last discarded bit is 1, there would be carry
   3996                         when rounding, otherwise there wouldn't. We use that
   3997                         fact and just add the value of the last discarded bit
   3998                         to the least sifgnificant bit of the shifted value
   3999                         from acc. */
   4000                      assign(t8,
   4001                             IRExpr_ITE(binop(Iop_CmpEQ32,
   4002                                              unop(Iop_8Uto32,
   4003                                                   mkexpr(t15)),
   4004                                              mkU32(0)),
   4005                                        mkU64(0x0ULL),
   4006                                        binop(Iop_And64,
   4007                                              binop(Iop_Shr64,
   4008                                                    mkexpr(t0),
   4009                                                    unop(Iop_32to8,
   4010                                                         binop(Iop_Sub32,
   4011                                                               unop(Iop_8Uto32,
   4012                                                                    mkexpr(t15)),
   4013                                                                    mkU32(1)))),
   4014                                              mkU64(0x1ULL))));
   4015 
   4016                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   4017                      /* Put rounded value in destination register. */
   4018                      putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
   4019 
   4020                      /* Repeat previous steps for the rounded value. */
   4021                      assign(t10, binop(Iop_CmpNE32,
   4022                                       unop(Iop_64HIto32,
   4023                                            mkexpr(t9)),
   4024                                       mkU32(0)));
   4025                      assign(t11, binop(Iop_CmpNE32,
   4026                                       binop(Iop_And32,
   4027                                             unop(Iop_64to32,
   4028                                                  mkexpr(t9)),
   4029                                             mkU32(0x80000000)),
   4030                                       mkU32(0)));
   4031 
   4032                      assign(t12, binop(Iop_CmpNE32,
   4033                                       unop(Iop_64HIto32,
   4034                                            mkexpr(t9)),
   4035                                       mkU32(0xffffffff)));
   4036                      assign(t13, binop(Iop_CmpNE32,
   4037                                       binop(Iop_And32,
   4038                                             unop(Iop_64to32,
   4039                                                  mkexpr(t9)),
   4040                                             mkU32(0x80000000)),
   4041                                       mkU32(0x80000000)));
   4042 
   4043                      assign(t14, binop(Iop_And32,
   4044                                       binop(Iop_Or32,
   4045                                             unop(Iop_1Sto32, mkexpr(t10)),
   4046                                             unop(Iop_1Sto32, mkexpr(t11))),
   4047                                       binop(Iop_Or32,
   4048                                             unop(Iop_1Sto32, mkexpr(t12)),
   4049                                             unop(Iop_1Sto32, mkexpr(t13)))));
   4050                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4051                                                     mkexpr(t14),
   4052                                                     mkU32(0)),
   4053                                               binop(Iop_Or32,
   4054                                                     getDSPControl(),
   4055                                                     mkU32(0x00800000)),
   4056                                               getDSPControl()));
   4057                      break;
   4058                   }
   4059                   case 0x6: {  /* EXTR_RS.W */
   4060                      DIP("extr_rs.w r%d, ac%d, %d", rt, ac, rs);
   4061                      vassert(!mode64);
   4062                      t0 = newTemp(Ity_I64);
   4063                      t1 = newTemp(Ity_I64);
   4064                      t2 = newTemp(Ity_I32);
   4065                      t3 = newTemp(Ity_I1);
   4066                      t4 = newTemp(Ity_I1);
   4067                      t5 = newTemp(Ity_I1);
   4068                      t6 = newTemp(Ity_I1);
   4069                      t7 = newTemp(Ity_I32);
   4070                      t8 = newTemp(Ity_I64);
   4071                      t9 = newTemp(Ity_I64);
   4072                      t10 = newTemp(Ity_I1);
   4073                      t11 = newTemp(Ity_I1);
   4074                      t12 = newTemp(Ity_I1);
   4075                      t13 = newTemp(Ity_I1);
   4076                      t14 = newTemp(Ity_I32);
   4077                      t16 = newTemp(Ity_I32);
   4078 
   4079                      assign(t0, getAcc(ac));
   4080                      if (0 == rs) {
   4081                         assign(t1, mkexpr(t0));
   4082                      } else {
   4083                         assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
   4084                      }
   4085 
   4086                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   4087                      assign(t3, binop(Iop_CmpNE32,
   4088                                       unop(Iop_64HIto32,
   4089                                            mkexpr(t1)),
   4090                                       mkU32(0)));
   4091                      assign(t4, binop(Iop_CmpNE32,
   4092                                       binop(Iop_And32,
   4093                                             unop(Iop_64to32,
   4094                                                  mkexpr(t1)),
   4095                                             mkU32(0x80000000)),
   4096                                       mkU32(0)));
   4097                      /* Check if bits 63..31 of the result in t1 aren't
   4098                         0x1ffffffff. */
   4099                      assign(t5, binop(Iop_CmpNE32,
   4100                                       unop(Iop_64HIto32,
   4101                                            mkexpr(t1)),
   4102                                       mkU32(0xffffffff)));
   4103                      assign(t6, binop(Iop_CmpNE32,
   4104                                       binop(Iop_And32,
   4105                                             unop(Iop_64to32,
   4106                                                  mkexpr(t1)),
   4107                                             mkU32(0x80000000)),
   4108                                       mkU32(0x80000000)));
   4109                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   4110                         control register. */
   4111                      assign(t7, binop(Iop_And32,
   4112                                       binop(Iop_Or32,
   4113                                             unop(Iop_1Sto32, mkexpr(t3)),
   4114                                             unop(Iop_1Sto32, mkexpr(t4))),
   4115                                       binop(Iop_Or32,
   4116                                             unop(Iop_1Sto32, mkexpr(t5)),
   4117                                             unop(Iop_1Sto32, mkexpr(t6)))));
   4118                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4119                                                     mkexpr(t7),
   4120                                                     mkU32(0)),
   4121                                               binop(Iop_Or32,
   4122                                                     getDSPControl(),
   4123                                                     mkU32(0x00800000)),
   4124                                               getDSPControl()));
   4125 
   4126                      /* If the last discarded bit is 1, there would be carry
   4127                         when rounding, otherwise there wouldn't. We use that
   4128                         fact and just add the value of the last discarded bit
   4129                         to the least sifgnificant bit of the shifted value
   4130                         from acc. */
   4131                      if (0 == rs) {
   4132                         assign(t8, mkU64(0x0ULL));
   4133                      } else {
   4134                         assign(t8, binop(Iop_And64,
   4135                                          binop(Iop_Shr64,
   4136                                                mkexpr(t0),
   4137                                                mkU8(rs-1)),
   4138                                          mkU64(0x1ULL)));
   4139                      }
   4140 
   4141                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   4142 
   4143                      /* Repeat previous steps for the rounded value. */
   4144                      assign(t10, binop(Iop_CmpNE32,
   4145                                       unop(Iop_64HIto32,
   4146                                            mkexpr(t9)),
   4147                                       mkU32(0)));
   4148                      assign(t11, binop(Iop_CmpNE32,
   4149                                       binop(Iop_And32,
   4150                                             unop(Iop_64to32,
   4151                                                  mkexpr(t9)),
   4152                                             mkU32(0x80000000)),
   4153                                       mkU32(0)));
   4154 
   4155                      assign(t12, binop(Iop_CmpNE32,
   4156                                       unop(Iop_64HIto32,
   4157                                            mkexpr(t9)),
   4158                                       mkU32(0xffffffff)));
   4159                      assign(t13, binop(Iop_CmpNE32,
   4160                                       binop(Iop_And32,
   4161                                             unop(Iop_64to32,
   4162                                                  mkexpr(t9)),
   4163                                             mkU32(0x80000000)),
   4164                                       mkU32(0x80000000)));
   4165 
   4166                      assign(t14, binop(Iop_And32,
   4167                                       binop(Iop_Or32,
   4168                                             unop(Iop_1Sto32, mkexpr(t10)),
   4169                                             unop(Iop_1Sto32, mkexpr(t11))),
   4170                                       binop(Iop_Or32,
   4171                                             unop(Iop_1Sto32, mkexpr(t12)),
   4172                                             unop(Iop_1Sto32, mkexpr(t13)))));
   4173                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4174                                                     mkexpr(t14),
   4175                                                     mkU32(0)),
   4176                                               binop(Iop_Or32,
   4177                                                     getDSPControl(),
   4178                                                     mkU32(0x00800000)),
   4179                                               getDSPControl()));
   4180 
   4181                      assign(t16, binop(Iop_And32,
   4182                                        unop(Iop_64HIto32,
   4183                                             mkexpr(t9)),
   4184                                        mkU32(0x80000000)));
   4185                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
   4186                                                   mkexpr(t14),
   4187                                                   mkU32(0)),
   4188                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   4189                                                              mkexpr(t16),
   4190                                                              mkU32(0)),
   4191                                                        mkU32(0x7fffffff),
   4192                                                        mkU32(0x80000000)),
   4193                                             unop(Iop_64to32, mkexpr(t9))));
   4194                      break;
   4195                   }
   4196                   case 0x7: {  /* EXTRV_RS.W */
   4197                      DIP("extrv_rs.w r%d, ac%d, r%d", rt, ac, rs);
   4198                      vassert(!mode64);
   4199                      t0 = newTemp(Ity_I64);
   4200                      t1 = newTemp(Ity_I64);
   4201                      t2 = newTemp(Ity_I32);
   4202                      t3 = newTemp(Ity_I1);
   4203                      t4 = newTemp(Ity_I1);
   4204                      t5 = newTemp(Ity_I1);
   4205                      t6 = newTemp(Ity_I1);
   4206                      t7 = newTemp(Ity_I32);
   4207                      t8 = newTemp(Ity_I64);
   4208                      t9 = newTemp(Ity_I64);
   4209                      t10 = newTemp(Ity_I1);
   4210                      t11 = newTemp(Ity_I1);
   4211                      t12 = newTemp(Ity_I1);
   4212                      t13 = newTemp(Ity_I1);
   4213                      t14 = newTemp(Ity_I32);
   4214                      t15 = newTemp(Ity_I32);
   4215                      t16 = newTemp(Ity_I32);
   4216                      t17 = newTemp(Ity_I1);
   4217 
   4218                      assign(t15, binop(Iop_And32,
   4219                                        getIReg(rs),
   4220                                        mkU32(0x1f)));
   4221                      assign(t17, binop(Iop_CmpEQ32,
   4222                                        mkexpr(t15),
   4223                                        mkU32(0)));
   4224                      assign(t0, getAcc(ac));
   4225                      assign(t1, IRExpr_ITE(mkexpr(t17),
   4226                                            mkexpr(t0),
   4227                                            binop(Iop_Sar64,
   4228                                                  mkexpr(t0),
   4229                                                  unop(Iop_32to8,
   4230                                                       mkexpr(t15)))));
   4231 
   4232                      /* Check if bits 63..31 of the result in t1 aren't 0. */
   4233                      assign(t3, binop(Iop_CmpNE32,
   4234                                       unop(Iop_64HIto32,
   4235                                            mkexpr(t1)),
   4236                                       mkU32(0)));
   4237                      assign(t4, binop(Iop_CmpNE32,
   4238                                       binop(Iop_And32,
   4239                                             unop(Iop_64to32,
   4240                                                  mkexpr(t1)),
   4241                                             mkU32(0x80000000)),
   4242                                       mkU32(0)));
   4243                      /* Check if bits 63..31 of the result in t1 aren't
   4244                         0x1ffffffff. */
   4245                      assign(t5, binop(Iop_CmpNE32,
   4246                                       unop(Iop_64HIto32,
   4247                                            mkexpr(t1)),
   4248                                       mkU32(0xffffffff)));
   4249                      assign(t6, binop(Iop_CmpNE32,
   4250                                       binop(Iop_And32,
   4251                                             unop(Iop_64to32,
   4252                                                  mkexpr(t1)),
   4253                                             mkU32(0x80000000)),
   4254                                       mkU32(0x80000000)));
   4255                      /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
   4256                         control register. */
   4257                      assign(t7, binop(Iop_And32,
   4258                                       binop(Iop_Or32,
   4259                                             unop(Iop_1Sto32, mkexpr(t3)),
   4260                                             unop(Iop_1Sto32, mkexpr(t4))),
   4261                                       binop(Iop_Or32,
   4262                                             unop(Iop_1Sto32, mkexpr(t5)),
   4263                                             unop(Iop_1Sto32, mkexpr(t6)))));
   4264                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4265                                                     mkexpr(t7),
   4266                                                     mkU32(0)),
   4267                                               binop(Iop_Or32,
   4268                                                     getDSPControl(),
   4269                                                     mkU32(0x00800000)),
   4270                                               getDSPControl()));
   4271 
   4272                      /* If the last discarded bit is 1, there would be carry
   4273                         when rounding, otherwise there wouldn't. We use that
   4274                         fact and just add the value of the last discarded bit
   4275                         to the least sifgnificant bit of the shifted value
   4276                         from acc. */
   4277                      assign(t8,
   4278                             IRExpr_ITE(mkexpr(t17),
   4279                                        mkU64(0x0ULL),
   4280                                        binop(Iop_And64,
   4281                                              binop(Iop_Shr64,
   4282                                                    mkexpr(t0),
   4283                                                    unop(Iop_32to8,
   4284                                                         binop(Iop_Sub32,
   4285                                                               mkexpr(t15),
   4286                                                               mkU32(1)))),
   4287                                              mkU64(0x1ULL))));
   4288 
   4289                      assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
   4290 
   4291                      /* Repeat previous steps for the rounded value. */
   4292                      assign(t10, binop(Iop_CmpNE32,
   4293                                       unop(Iop_64HIto32,
   4294                                            mkexpr(t9)),
   4295                                       mkU32(0)));
   4296                      assign(t11, binop(Iop_CmpNE32,
   4297                                       binop(Iop_And32,
   4298                                             unop(Iop_64to32,
   4299                                                  mkexpr(t9)),
   4300                                             mkU32(0x80000000)),
   4301                                       mkU32(0)));
   4302 
   4303                      assign(t12, binop(Iop_CmpNE32,
   4304                                       unop(Iop_64HIto32,
   4305                                            mkexpr(t9)),
   4306                                       mkU32(0xffffffff)));
   4307                      assign(t13, binop(Iop_CmpNE32,
   4308                                       binop(Iop_And32,
   4309                                             unop(Iop_64to32,
   4310                                                  mkexpr(t9)),
   4311                                             mkU32(0x80000000)),
   4312                                       mkU32(0x80000000)));
   4313 
   4314                      assign(t14, binop(Iop_And32,
   4315                                       binop(Iop_Or32,
   4316                                             unop(Iop_1Sto32, mkexpr(t10)),
   4317                                             unop(Iop_1Sto32, mkexpr(t11))),
   4318                                       binop(Iop_Or32,
   4319                                             unop(Iop_1Sto32, mkexpr(t12)),
   4320                                             unop(Iop_1Sto32, mkexpr(t13)))));
   4321                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4322                                                     mkexpr(t14),
   4323                                                     mkU32(0)),
   4324                                               binop(Iop_Or32,
   4325                                                     getDSPControl(),
   4326                                                     mkU32(0x00800000)),
   4327                                               getDSPControl()));
   4328 
   4329                      assign(t16, binop(Iop_And32,
   4330                                        unop(Iop_64HIto32,
   4331                                             mkexpr(t9)),
   4332                                        mkU32(0x80000000)));
   4333                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
   4334                                                   mkexpr(t14),
   4335                                                   mkU32(0)),
   4336                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   4337                                                              mkexpr(t16),
   4338                                                              mkU32(0)),
   4339                                                        mkU32(0x7fffffff),
   4340                                                        mkU32(0x80000000)),
   4341                                             unop(Iop_64to32, mkexpr(t9))));
   4342                      break;
   4343                   }
   4344                   case 0xA: {  /* EXTPDP */
   4345                      DIP("extpdp r%d, ac%d, %d", rt, ac, rs);
   4346                      vassert(!mode64);
   4347                      t0 = newTemp(Ity_I64);
   4348                      t1 = newTemp(Ity_I32);
   4349                      t2 = newTemp(Ity_I1);
   4350                      t3 = newTemp(Ity_I1);
   4351                      t4 = newTemp(Ity_I8);
   4352                      t5 = newTemp(Ity_I64);
   4353                      t6 = newTemp(Ity_I64);
   4354                      t7 = newTemp(Ity_I32);
   4355                      t8 = newTemp(Ity_I32);
   4356 
   4357                      assign(t0, getAcc(ac));
   4358                      /* Extract pos field of DSPControl register. */
   4359                      assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   4360 
   4361                      /* Check if (pos - size) >= 0 [size <= pos]
   4362                         if (pos < size)
   4363                            put 1 to EFI field of DSPControl register
   4364                         else
   4365                            extract bits from acc and put 0 to EFI field of
   4366                            DSPCtrl */
   4367                      assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
   4368 
   4369                      assign(t8, binop(Iop_Or32,
   4370                                       binop(Iop_And32,
   4371                                             getDSPControl(),
   4372                                             mkU32(0xffffbfc0)),
   4373                                       binop(Iop_And32,
   4374                                             binop(Iop_Sub32,
   4375                                                   binop(Iop_And32,
   4376                                                         getDSPControl(),
   4377                                                         mkU32(0x3f)),
   4378                                                   mkU32(rs+1)),
   4379                                             mkU32(0x3f))));
   4380                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   4381                                               binop(Iop_Or32,
   4382                                                      binop(Iop_And32,
   4383                                                            getDSPControl(),
   4384                                                            mkU32(0xffffbfff)),
   4385                                                      mkU32(0x4000)),
   4386                                               mkexpr(t8)));
   4387 
   4388                      /* If pos <= 31, shift right the value from the acc
   4389                         (pos-size) times and take (size+1) bits from the least
   4390                         significant positions. Otherwise, shift left the value
   4391                         (63-pos) times, take (size+1) bits from the most
   4392                         significant positions and shift right (31-size) times.
   4393                      */
   4394                      assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
   4395 
   4396                      assign(t4,
   4397                             IRExpr_ITE(mkexpr(t3),
   4398                                        unop(Iop_32to8,
   4399                                             binop(Iop_Sub32,
   4400                                                   mkexpr(t1), mkU32(rs))),
   4401                                        unop(Iop_32to8,
   4402                                             binop(Iop_Sub32,
   4403                                                   mkU32(63), mkexpr(t1)))));
   4404 
   4405                      assign(t5, IRExpr_ITE(mkexpr(t3),
   4406                                            binop(Iop_Shr64,
   4407                                                  mkexpr(t0), mkexpr(t4)),
   4408                                            binop(Iop_Shl64,
   4409                                                  mkexpr(t0), mkexpr(t4))));
   4410 
   4411                      /* t6 holds a mask for bit extraction. */
   4412                      assign(t6,
   4413                             IRExpr_ITE(mkexpr(t3),
   4414                                        unop(Iop_Not64,
   4415                                             binop(Iop_Shl64,
   4416                                                   mkU64(0xffffffffffffffffULL),
   4417                                                   mkU8(rs+1))),
   4418                                        unop(Iop_Not64,
   4419                                             binop(Iop_Shr64,
   4420                                                   mkU64(0xffffffffffffffffULL),
   4421                                                   mkU8(rs+1)))));
   4422 
   4423                      assign(t7, IRExpr_ITE(mkexpr(t3),
   4424                                            unop(Iop_64to32,
   4425                                                 binop(Iop_And64,
   4426                                                       mkexpr(t5),
   4427                                                       mkexpr(t6))),
   4428                                            binop(Iop_Shr32,
   4429                                                  unop(Iop_64HIto32,
   4430                                                       binop(Iop_And64,
   4431                                                             mkexpr(t5),
   4432                                                             mkexpr(t6))),
   4433                                                  mkU8(31-rs))));
   4434 
   4435                      putIReg(rt, mkexpr(t7));
   4436                      break;
   4437                   }
   4438                   case 0xB: {  /* EXTPDPV */
   4439                      DIP("extpdpv r%d, ac%d, r%d", rt, ac, rs);
   4440                      vassert(!mode64);
   4441                      t0 = newTemp(Ity_I64);
   4442                      t1 = newTemp(Ity_I32);
   4443                      t2 = newTemp(Ity_I1);
   4444                      t3 = newTemp(Ity_I1);
   4445                      t4 = newTemp(Ity_I8);
   4446                      t5 = newTemp(Ity_I64);
   4447                      t6 = newTemp(Ity_I64);
   4448                      t7 = newTemp(Ity_I32);
   4449                      t8 = newTemp(Ity_I32);
   4450                      t9 = newTemp(Ity_I32);
   4451 
   4452                      assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
   4453                      assign(t0, getAcc(ac));
   4454                      /* Extract pos field of DSPControl register. */
   4455                      assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   4456 
   4457                      /* Check if (pos - size) >= 0 [size <= pos]
   4458                         if (pos < size)
   4459                            put 1 to EFI field of DSPControl register
   4460                         else
   4461                            extract bits from acc and put 0 to EFI field of
   4462                            DSPCtrl */
   4463                      assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
   4464 
   4465                      assign(t9, binop(Iop_Or32,
   4466                                       binop(Iop_And32,
   4467                                             getDSPControl(),
   4468                                             mkU32(0xffffbfc0)),
   4469                                       binop(Iop_And32,
   4470                                             binop(Iop_Sub32,
   4471                                                   binop(Iop_And32,
   4472                                                         getDSPControl(),
   4473                                                         mkU32(0x3f)),
   4474                                                   binop(Iop_Add32,
   4475                                                         mkexpr(t8),
   4476                                                         mkU32(0x1))),
   4477                                             mkU32(0x3f))));
   4478                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   4479                                               binop(Iop_Or32,
   4480                                                     binop(Iop_And32,
   4481                                                           getDSPControl(),
   4482                                                           mkU32(0xffffbfff)),
   4483                                                     mkU32(0x4000)),
   4484                                               mkexpr(t9)));
   4485 
   4486                      /* If pos <= 31, shift right the value from the acc
   4487                         (pos-size) times and take (size+1) bits from the least
   4488                         significant positions. Otherwise, shift left the value
   4489                         (63-pos) times, take (size+1) bits from the most
   4490                         significant positions and shift right (31-size) times.
   4491                      */
   4492                      assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
   4493 
   4494                      assign(t4,
   4495                             IRExpr_ITE(mkexpr(t3),
   4496                                       unop(Iop_32to8,
   4497                                            binop(Iop_Sub32,
   4498                                                  mkexpr(t1), mkexpr(t8))),
   4499                                       unop(Iop_32to8,
   4500                                            binop(Iop_Sub32,
   4501                                                  mkU32(63), mkexpr(t1)))));
   4502 
   4503                      assign(t5, IRExpr_ITE(mkexpr(t3),
   4504                                            binop(Iop_Shr64,
   4505                                                  mkexpr(t0), mkexpr(t4)),
   4506                                            binop(Iop_Shl64,
   4507                                                  mkexpr(t0), mkexpr(t4))));
   4508 
   4509                      /* t6 holds a mask for bit extraction. */
   4510                      assign(t6,
   4511                             IRExpr_ITE(mkexpr(t3),
   4512                                        unop(Iop_Not64,
   4513                                             binop(Iop_Shl64,
   4514                                                   mkU64(0xffffffffffffffffULL),
   4515                                                   unop(Iop_32to8,
   4516                                                        binop(Iop_Add32,
   4517                                                              mkexpr(t8),
   4518                                                              mkU32(1))))),
   4519                                        unop(Iop_Not64,
   4520                                             binop(Iop_Shr64,
   4521                                                   mkU64(0xffffffffffffffffULL),
   4522                                                   unop(Iop_32to8,
   4523                                                        binop(Iop_Add32,
   4524                                                              mkexpr(t8),
   4525                                                              mkU32(1)))))));
   4526 
   4527                      assign(t7, IRExpr_ITE(mkexpr(t3),
   4528                                            unop(Iop_64to32,
   4529                                                 binop(Iop_And64,
   4530                                                       mkexpr(t5),
   4531                                                       mkexpr(t6))),
   4532                                            binop(Iop_Shr32,
   4533                                                  unop(Iop_64HIto32,
   4534                                                       binop(Iop_And64,
   4535                                                             mkexpr(t5),
   4536                                                             mkexpr(t6))),
   4537                                                  unop(Iop_32to8,
   4538                                                       binop(Iop_Sub32,
   4539                                                             mkU32(31),
   4540                                                             mkexpr(t8))))));
   4541 
   4542                      putIReg(rt, mkexpr(t7));
   4543                      break;
   4544                   }
   4545                   case 0xE: {  /* EXTR_S.H */
   4546                      DIP("extr_s.h r%d, ac%d, %d", rt, ac, rs);
   4547                      vassert(!mode64);
   4548                      t0 = newTemp(Ity_I64);
   4549                      t1 = newTemp(Ity_I64);
   4550                      t2 = newTemp(Ity_I32);
   4551                      t3 = newTemp(Ity_I64);
   4552                      t4 = newTemp(Ity_I32);
   4553                      t5 = newTemp(Ity_I32);
   4554                      t6 = newTemp(Ity_I64);
   4555                      t7 = newTemp(Ity_I32);
   4556                      t9 = newTemp(Ity_I32);
   4557 
   4558                      assign(t0, getAcc(ac));
   4559 
   4560                      assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
   4561 
   4562                      assign(t2, binop(Iop_Or32,
   4563                                       getDSPControl(), mkU32(0x00800000)));
   4564 
   4565                      assign(t9, binop(Iop_And32,
   4566                                       unop(Iop_64to32,
   4567                                            mkexpr(t1)),
   4568                                       mkU32(0x80000000)));
   4569                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4570                                                     mkexpr(t9),
   4571                                                     binop(Iop_And32,
   4572                                                           unop(Iop_64HIto32,
   4573                                                                mkexpr(t0)),
   4574                                                           mkU32(0x80000000))),
   4575                                               mkexpr(t2),
   4576                                               getDSPControl()));
   4577 
   4578                      /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
   4579                         1. subtract 0x7fff from t1
   4580                         2. if the resulting number is positive (sign bit = 0)
   4581                            and any of the other bits is 1, the value is > 0. */
   4582                      assign(t3, binop(Iop_Sub64,
   4583                                       mkexpr(t1),
   4584                                       mkU64(0x0000000000007fffULL)));
   4585                      assign(t4, binop(Iop_And32,
   4586                                        binop(Iop_Or32,
   4587                                             unop(Iop_1Sto32,
   4588                                                  binop(Iop_CmpNE32,
   4589                                                        mkU32(0),
   4590                                                        binop(Iop_And32,
   4591                                                              unop(Iop_64HIto32,
   4592                                                                   mkexpr(t3)),
   4593                                                              mkU32(0x7fffffff)))),
   4594                                             unop(Iop_1Sto32,
   4595                                                  binop(Iop_CmpNE32,
   4596                                                        mkU32(0),
   4597                                                        unop(Iop_64to32,
   4598                                                             mkexpr(t3))))),
   4599                                        unop(Iop_1Sto32,
   4600                                             binop(Iop_CmpEQ32,
   4601                                                   binop(Iop_And32,
   4602                                                         unop(Iop_64HIto32,
   4603                                                                   mkexpr(t3)),
   4604                                                              mkU32(0x80000000)),
   4605                                                   mkU32(0)))));
   4606                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4607                                                     mkU32(0),
   4608                                                     mkexpr(t4)),
   4609                                               binop(Iop_Or32,
   4610                                                     getDSPControl(),
   4611                                                     mkU32(0x00800000)),
   4612                                               getDSPControl()));
   4613                      /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
   4614                         1. subtract t1 from 0xffffffffffff8000
   4615                         2. if the resulting number is positive (sign bit = 0)
   4616                             and any of the other bits is 1, the value is > 0 */
   4617                      assign(t6, binop(Iop_Sub64,
   4618                                        mkU64(0xffffffffffff8000ULL),
   4619                                        mkexpr(t1)));
   4620                      assign(t7, binop(Iop_And32,
   4621                                       binop(Iop_Or32,
   4622                                             unop(Iop_1Sto32,
   4623                                                  binop(Iop_CmpNE32,
   4624                                                        mkU32(0),
   4625                                                        binop(Iop_And32,
   4626                                                              unop(Iop_64HIto32,
   4627                                                                   mkexpr(t6)),
   4628                                                              mkU32(0x7fffffff)))),
   4629                                             unop(Iop_1Sto32,
   4630                                                  binop(Iop_CmpNE32,
   4631                                                        mkU32(0),
   4632                                                        unop(Iop_64to32,
   4633                                                             mkexpr(t6))))),
   4634                                       unop(Iop_1Sto32,
   4635                                             binop(Iop_CmpEQ32,
   4636                                                   binop(Iop_And32,
   4637                                                         unop(Iop_64HIto32,
   4638                                                                   mkexpr(t6)),
   4639                                                              mkU32(0x80000000)),
   4640                                                   mkU32(0)))));
   4641                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4642                                                     mkU32(0),
   4643                                                     mkexpr(t7)),
   4644                                               binop(Iop_Or32,
   4645                                                     getDSPControl(),
   4646                                                     mkU32(0x00800000)),
   4647                                               getDSPControl()));
   4648                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
   4649                                                     mkU32(0),
   4650                                                     mkexpr(t4)),
   4651                                             mkU32(0x00007fff),
   4652                                             IRExpr_ITE(binop(Iop_CmpNE32,
   4653                                                              mkU32(0),
   4654                                                              mkexpr(t7)),
   4655                                                        mkU32(0xffff8000),
   4656                                                        unop(Iop_64to32,
   4657                                                             mkexpr(t1)))));
   4658                      break;
   4659                   }
   4660                   case 0xF: {  /* EXTRV_S.H */
   4661                      DIP("extrv_s.h r%d, ac%d, %d", rt, ac, rs);
   4662                      vassert(!mode64);
   4663                      t0 = newTemp(Ity_I64);
   4664                      t1 = newTemp(Ity_I64);
   4665                      t2 = newTemp(Ity_I32);
   4666                      t3 = newTemp(Ity_I64);
   4667                      t4 = newTemp(Ity_I32);
   4668                      t5 = newTemp(Ity_I32);
   4669                      t6 = newTemp(Ity_I64);
   4670                      t7 = newTemp(Ity_I32);
   4671                      t9 = newTemp(Ity_I32);
   4672 
   4673                      assign(t0, getAcc(ac));
   4674 
   4675                      assign(t1, binop(Iop_Sar64,
   4676                                       mkexpr(t0),
   4677                                       unop(Iop_32to8,
   4678                                            binop(Iop_And32,
   4679                                                  getIReg(rs),
   4680                                                  mkU32(0x1f)))));
   4681 
   4682                      assign(t2, binop(Iop_Or32,
   4683                                       getDSPControl(), mkU32(0x00800000)));
   4684 
   4685                      assign(t9, binop(Iop_And32,
   4686                                       unop(Iop_64to32,
   4687                                            mkexpr(t1)),
   4688                                       mkU32(0x80000000)));
   4689                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4690                                                     mkexpr(t9),
   4691                                                     binop(Iop_And32,
   4692                                                           unop(Iop_64HIto32,
   4693                                                                mkexpr(t0)),
   4694                                                           mkU32(0x80000000))),
   4695                                               mkexpr(t2),
   4696                                               getDSPControl()));
   4697 
   4698                      /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
   4699                         1. subtract 0x7fff from t1
   4700                         2. if the resulting number is positive (sign bit = 0)
   4701                            and any of the other bits is 1, the value is > 0. */
   4702                      assign(t3, binop(Iop_Sub64,
   4703                                       mkexpr(t1),
   4704                                       mkU64(0x0000000000007fffULL)));
   4705                      assign(t4, binop(Iop_And32,
   4706                                        binop(Iop_Or32,
   4707                                             unop(Iop_1Sto32,
   4708                                                  binop(Iop_CmpNE32,
   4709                                                        mkU32(0),
   4710                                                        binop(Iop_And32,
   4711                                                              unop(Iop_64HIto32,
   4712                                                                   mkexpr(t3)),
   4713                                                              mkU32(0x7fffffff)))),
   4714                                             unop(Iop_1Sto32,
   4715                                                  binop(Iop_CmpNE32,
   4716                                                        mkU32(0),
   4717                                                        unop(Iop_64to32,
   4718                                                             mkexpr(t3))))),
   4719                                        unop(Iop_1Sto32,
   4720                                             binop(Iop_CmpEQ32,
   4721                                                   binop(Iop_And32,
   4722                                                         unop(Iop_64HIto32,
   4723                                                                   mkexpr(t3)),
   4724                                                              mkU32(0x80000000)),
   4725                                                   mkU32(0)))));
   4726                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4727                                                     mkU32(0),
   4728                                                     mkexpr(t4)),
   4729                                               binop(Iop_Or32,
   4730                                                     getDSPControl(),
   4731                                                     mkU32(0x00800000)),
   4732                                               getDSPControl()));
   4733                      /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
   4734                         1. subtract t1 from 0xffffffffffff8000
   4735                         2. if the resulting number is positive (sign bit = 0)
   4736                             and any of the other bits is 1, the value is > 0 */
   4737                      assign(t6, binop(Iop_Sub64,
   4738                                        mkU64(0xffffffffffff8000ULL),
   4739                                        mkexpr(t1)));
   4740                      assign(t7, binop(Iop_And32,
   4741                                       binop(Iop_Or32,
   4742                                             unop(Iop_1Sto32,
   4743                                                  binop(Iop_CmpNE32,
   4744                                                        mkU32(0),
   4745                                                        binop(Iop_And32,
   4746                                                              unop(Iop_64HIto32,
   4747                                                                   mkexpr(t6)),
   4748                                                              mkU32(0x7fffffff)))),
   4749                                             unop(Iop_1Sto32,
   4750                                                  binop(Iop_CmpNE32,
   4751                                                        mkU32(0),
   4752                                                        unop(Iop_64to32,
   4753                                                             mkexpr(t6))))),
   4754                                       unop(Iop_1Sto32,
   4755                                             binop(Iop_CmpEQ32,
   4756                                                   binop(Iop_And32,
   4757                                                         unop(Iop_64HIto32,
   4758                                                                   mkexpr(t6)),
   4759                                                              mkU32(0x80000000)),
   4760                                                   mkU32(0)))));
   4761                      putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
   4762                                                     mkU32(0),
   4763                                                     mkexpr(t7)),
   4764                                               binop(Iop_Or32,
   4765                                                     getDSPControl(),
   4766                                                     mkU32(0x00800000)),
   4767                                               getDSPControl()));
   4768                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
   4769                                                     mkU32(0),
   4770                                                     mkexpr(t4)),
   4771                                             mkU32(0x00007fff),
   4772                                             IRExpr_ITE(binop(Iop_CmpNE32,
   4773                                                              mkU32(0),
   4774                                                              mkexpr(t7)),
   4775                                                        mkU32(0xffff8000),
   4776                                                        unop(Iop_64to32,
   4777                                                             mkexpr(t1)))));
   4778                      break;
   4779                   }
   4780                   case 0x12: {  /* RDDSP*/
   4781                      DIP("rddsp r%d, mask 0x%x", rd, rddsp_mask);
   4782                      vassert(!mode64);
   4783 
   4784                      putIReg(rd, mkU32(0x0));
   4785 
   4786                      if ((rddsp_mask & 0x1) == 0x1) {
   4787                         /* Read pos field (bits 5-0) of DSPControl register. */
   4788                         putIReg(rd, binop(Iop_Or32,
   4789                                           getIReg(rd),
   4790                                           binop(Iop_And32,
   4791                                                 getDSPControl(),
   4792                                                 mkU32(0x0000003F))));
   4793                      }
   4794 
   4795                      if ((rddsp_mask & 0x2) == 0x2) {
   4796                         /* Read scount field (bits 12-7) of DSPControl
   4797                            register. */
   4798                         putIReg(rd, binop(Iop_Or32,
   4799                                           getIReg(rd),
   4800                                           binop(Iop_And32,
   4801                                                 getDSPControl(),
   4802                                                 mkU32(0x00001F80))));
   4803                      }
   4804 
   4805                      if ((rddsp_mask & 0x4) == 0x4) {
   4806                         /* Read C field (bit 13) of DSPControl register. */
   4807                         putIReg(rd, binop(Iop_Or32,
   4808                                           getIReg(rd),
   4809                                           binop(Iop_And32,
   4810                                                 getDSPControl(),
   4811                                                 mkU32(0x00002000))));
   4812                      }
   4813 
   4814                      if ((rddsp_mask & 0x8) == 0x8) {
   4815                         /* Read outflag field (bit s 23-16) of DSPControl
   4816                            register. */
   4817                         putIReg(rd, binop(Iop_Or32,
   4818                                           getIReg(rd),
   4819                                           binop(Iop_And32,
   4820                                                 getDSPControl(),
   4821                                                 mkU32(0x00FF0000))));
   4822                      }
   4823 
   4824                      if ((rddsp_mask & 0x10) == 0x10) {
   4825                         /* Read ccond field (bits 31-24) of DSPControl
   4826                            register. */
   4827                         putIReg(rd, binop(Iop_Or32,
   4828                                           getIReg(rd),
   4829                                           binop(Iop_And32,
   4830                                                 getDSPControl(),
   4831                                                 mkU32(0xFF000000))));
   4832                      }
   4833 
   4834                      if ((rddsp_mask & 0x20) == 0x20) {
   4835                         /* Read EFI field (bit 14) of DSPControl register. */
   4836                         putIReg(rd, binop(Iop_Or32,
   4837                                           getIReg(rd),
   4838                                           binop(Iop_And32,
   4839                                                 getDSPControl(),
   4840                                                 mkU32(0x00004000))));
   4841                      }
   4842 
   4843                      if ((rddsp_mask & 0x3f) == 0x3f) {
   4844                         /* Read all fields of DSPControl register. */
   4845                         putIReg(rd, getDSPControl());
   4846                      }
   4847                      break;
   4848                   }
   4849                   case 0x13: {  /* WRDSP */
   4850                      DIP("wrdsp r%d, mask 0x%x", rs, wrdsp_mask);
   4851                      vassert(!mode64);
   4852 
   4853                      if ((wrdsp_mask & 0x3f) == 0x3f) {
   4854                         /* If mips64 put all fields of rs, except bit 15 and bit
   4855                            6, to DSPControl register, otherwise put all except
   4856                            bits 15, 6 and bits 31..28. */
   4857                         putDSPControl(mode64 ?
   4858                                       binop(Iop_And32,
   4859                                             getIReg(rs),
   4860                                             mkU32(0xffff7fbf)) :
   4861                                       binop(Iop_And32,
   4862                                             getIReg(rs),
   4863                                             mkU32(0x0fff7fbf)));
   4864                      } else {
   4865                         if ((wrdsp_mask & 0x1) == 0x1) {
   4866                            /* Put bits 5-0 of rs to DSPControl register pos
   4867                               field. */
   4868                            putDSPControl(binop(Iop_Or32,
   4869                                                binop(Iop_And32,
   4870                                                      getDSPControl(),
   4871                                                      mkU32(0xFFFF7F40)),
   4872                                                binop(Iop_And32,
   4873                                                      getIReg(rs),
   4874                                                      mkU32(0x0000003F))));
   4875                         }
   4876 
   4877                         if ((wrdsp_mask & 0x2) == 0x2) {
   4878                            /* Put bits 12-7 of rs to DSPControl scount field. */
   4879                            putDSPControl(binop(Iop_Or32,
   4880                                                binop(Iop_And32,
   4881                                                      getDSPControl(),
   4882                                                      mkU32(0xFFFFE03F)),
   4883                                                binop(Iop_And32,
   4884                                                      getIReg(rs),
   4885                                                      mkU32(0x00001F80))));
   4886                         }
   4887 
   4888                         if ((wrdsp_mask & 0x4) == 0x4) {
   4889                            /* Put bit 13 of rs to DSPControl register C
   4890                               field. */
   4891                            putDSPControl(binop(Iop_Or32,
   4892                                                binop(Iop_And32,
   4893                                                      getDSPControl(),
   4894                                                      mkU32(0xFFFF5FBF)),
   4895                                                binop(Iop_And32,
   4896                                                      getIReg(rs),
   4897                                                      mkU32(0x00002000))));
   4898                         }
   4899 
   4900                         if ((wrdsp_mask & 0x8) == 0x8) {
   4901                            /* Put bits 23-16 of rs to DSPControl reg outflag
   4902                               field. */
   4903                            putDSPControl(binop(Iop_Or32,
   4904                                                binop(Iop_And32,
   4905                                                      getDSPControl(),
   4906                                                      mkU32(0xFF007FBF)),
   4907                                                binop(Iop_And32,
   4908                                                      getIReg(rs),
   4909                                                      mkU32(0x00FF0000))));
   4910                         }
   4911 
   4912                         if ((wrdsp_mask & 0x10) == 0x10) {
   4913                            /* Put bits 31-24 of rs to DSPControl reg ccond
   4914                               field. */
   4915                            putDSPControl(binop(Iop_Or32,
   4916                                                binop(Iop_And32,
   4917                                                      getDSPControl(),
   4918                                                      mkU32(0x00FF7FBF)),
   4919                                                binop(Iop_And32,
   4920                                                      getIReg(rs),
   4921                                                      mode64 ? mkU32(0xFF000000)
   4922                                                             : mkU32(0x0F000000))
   4923                                                )
   4924                                         );
   4925                         }
   4926 
   4927                         if ((wrdsp_mask & 0x20) == 0x20) {
   4928                            /* Put bit 14 of rs to DSPControl register EFI
   4929                               field. */
   4930                            putDSPControl(binop(Iop_Or32,
   4931                                                binop(Iop_And32,
   4932                                                      getDSPControl(),
   4933                                                      mkU32(0xFFFF3FBF)),
   4934                                                binop(Iop_And32,
   4935                                                      getIReg(rs),
   4936                                                      mkU32(0x00004000))));
   4937                         }
   4938                      }
   4939                      break;
   4940                   }
   4941                   case 0x1A: {  /* SHILO */
   4942                      DIP("shilo ac%d, %d", ac, shift);
   4943                      vassert(!mode64);
   4944                      t0 = newTemp(Ity_I64);
   4945                      t1 = newTemp(Ity_I64);
   4946 
   4947                      assign(t0, getAcc(ac));
   4948 
   4949                      putAcc(ac, mkexpr(t0));
   4950 
   4951                      if (0x20 == (shift & 0x3f)) {
   4952                         putAcc(ac, binop(Iop_32HLto64,
   4953                                          unop(Iop_64to32, mkexpr(t0)),
   4954                                          mkU32(0x0)));
   4955                      } else if (0x20 == (shift & 0x20)) {
   4956                         assign(t1, binop(Iop_Shl64,
   4957                                          mkexpr(t0),
   4958                                          unop(Iop_32to8,
   4959                                               binop(Iop_Add32,
   4960                                                     unop(Iop_Not32,
   4961                                                          mkU32(shift)),
   4962                                                     mkU32(0x1)))));
   4963 
   4964                         putAcc(ac, mkexpr(t1));
   4965                      } else {
   4966                         assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
   4967 
   4968                         putAcc(ac, mkexpr(t1));
   4969                      }
   4970                      break;
   4971                   }
   4972                   case 0x1B: {  /* SHILOV */
   4973                      DIP("shilov ac%d, r%d", ac, rs);
   4974                      vassert(!mode64);
   4975                      t0 = newTemp(Ity_I64);
   4976                      t1 = newTemp(Ity_I32);
   4977                      t2 = newTemp(Ity_I1);
   4978                      t3 = newTemp(Ity_I64);
   4979                      t4 = newTemp(Ity_I64);
   4980 
   4981                      assign(t0, getAcc(ac));
   4982                      assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
   4983                      assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
   4984                      assign(t3, binop(Iop_Shl64,
   4985                                       mkexpr(t0),
   4986                                       unop(Iop_32to8,
   4987                                            binop(Iop_Add32,
   4988                                                  unop(Iop_Not32,
   4989                                                       mkexpr(t1)),
   4990                                                  mkU32(0x1)))));
   4991                      assign(t4, binop(Iop_Shr64,
   4992                                       mkexpr(t0),
   4993                                       unop(Iop_32to8,
   4994                                            mkexpr(t1))));
   4995 
   4996                      putAcc(ac,
   4997                             IRExpr_ITE(mkexpr(t2),
   4998                                        binop(Iop_32HLto64,
   4999                                              unop(Iop_64to32, mkexpr(t0)),
   5000                                              mkU32(0x0)),
   5001                                        IRExpr_ITE(binop(Iop_CmpEQ32,
   5002                                                         binop(Iop_And32,
   5003                                                               mkexpr(t1),
   5004                                                               mkU32(0x20)),
   5005                                                         mkU32(0x20)),
   5006                                                   mkexpr(t3),
   5007                                                   mkexpr(t4))));
   5008                      break;
   5009                   }
   5010                   case 0x1F: {  /* MTHLIP */
   5011                      DIP("mthlip r%d, ac%d", rs, ac);
   5012                      vassert(!mode64);
   5013                      t0 = newTemp(Ity_I64);
   5014                      t1 = newTemp(Ity_I32);
   5015                      t2 = newTemp(Ity_I32);
   5016                      t3 = newTemp(Ity_I1);
   5017 
   5018                      assign(t0, getAcc(ac));
   5019                      putAcc(ac, binop(Iop_32HLto64,
   5020                                       unop(Iop_64to32, mkexpr(t0)),
   5021                                       getIReg(rs)));
   5022                      assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   5023                      putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
   5024                                                     mkU32(32),
   5025                                                     mkexpr(t1)),
   5026                                               binop(Iop_Or32,
   5027                                                     binop(Iop_Sub32,
   5028                                                           mkexpr(t1),
   5029                                                           mkU32(32)),
   5030                                                    binop(Iop_And32,
   5031                                                          getDSPControl(),
   5032                                                          mkU32(0xffffffc0))),
   5033                                               binop(Iop_Or32,
   5034                                                     binop(Iop_Add32,
   5035                                                           mkexpr(t1),
   5036                                                           mkU32(32)),
   5037                                                     binop(Iop_And32,
   5038                                                           getDSPControl(),
   5039                                                           mkU32(0xffffffc0)))));
   5040                      break;
   5041                   }
   5042                   default:
   5043                      return -1;
   5044                }
   5045                break;  /* end of EXTR.W */
   5046             }
   5047             case 0xA: {  /* LX */
   5048                switch(sa) {
   5049                   case 0x0: {  /* LWX */
   5050                      DIP("lwx r%d, r%d(r%d)", rd, rt, rs);
   5051                      vassert(!mode64);
   5052                      t0 = newTemp(Ity_I32);
   5053 
   5054                      assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
   5055 
   5056                      putIReg(rd, load(Ity_I32, mkexpr(t0)));
   5057                      break;
   5058                   }
   5059                   case 0x4: {  /* LHX */
   5060                      DIP("lhx r%d, r%d(r%d)", rd, rt, rs);
   5061                      vassert(!mode64);
   5062                      t0 = newTemp(Ity_I32);
   5063 
   5064                      assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
   5065 
   5066                      putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
   5067                      break;
   5068                   }
   5069                   case 0x6: {  /* LBUX */
   5070                      DIP("lbux r%d, r%d(r%d)", rd, rt, rs);
   5071                      vassert(!mode64);
   5072                      t0 = newTemp(Ity_I32);
   5073 
   5074                      assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
   5075 
   5076                      putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
   5077                      break;
   5078                   }
   5079                   default:
   5080                      return -1;
   5081                }
   5082                break;  /* end of LX */
   5083             }
   5084             case 0xC: {  /* INSV */
   5085                switch(sa) {
   5086                   case 0x0: {  /* INSV */
   5087                      DIP("insv r%d, r%d", rt, rs);
   5088                      vassert(!mode64);
   5089 
   5090                      t0 = newTemp(Ity_I32);
   5091                      t1 = newTemp(Ity_I32);
   5092                      t2 = newTemp(Ity_I8);
   5093                      t3 = newTemp(Ity_I8);
   5094                      t4 = newTemp(Ity_I32);
   5095                      t5 = newTemp(Ity_I1);
   5096                      t6 = newTemp(Ity_I32);
   5097                      t7 = newTemp(Ity_I32);
   5098                      t8 = newTemp(Ity_I32);
   5099                      t9 = newTemp(Ity_I32);
   5100 
   5101                      /* t0 <- pos field of DSPControl register. */
   5102                      assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
   5103                      /* t1 <- scount field of DSPControl register. */
   5104                      assign(t1, binop(Iop_Shr32,
   5105                                       binop(Iop_And32,
   5106                                             getDSPControl(),
   5107                                             mkU32(0x1f80)),
   5108                                       mkU8(7)));
   5109 
   5110                      assign(t2, unop(Iop_32to8,
   5111                                      binop(Iop_Add32,
   5112                                            mkexpr(t1),
   5113                                            mkexpr(t0))));
   5114 
   5115                      /* 32-(pos+size) most significant bits of rt. */
   5116                      assign(t6, binop(Iop_Shl32,
   5117                                       binop(Iop_Shr32,
   5118                                             getIReg(rt),
   5119                                             mkexpr(t2)),
   5120                                       mkexpr(t2)));
   5121 
   5122                      assign(t3, unop(Iop_32to8,
   5123                                      binop(Iop_Sub32,
   5124                                            mkU32(32),
   5125                                            mkexpr(t0))));
   5126                      /* Pos least significant bits of rt. */
   5127                      assign(t7, binop(Iop_Shr32,
   5128                                       binop(Iop_Shl32,
   5129                                             getIReg(rt),
   5130                                             mkexpr(t3)),
   5131                                       mkexpr(t3)));
   5132 
   5133                      /* Size least significant bits of rs,
   5134                         shifted to appropriate position. */
   5135                      assign(t8, binop(Iop_Shl32,
   5136                                       binop(Iop_And32,
   5137                                             getIReg(rs),
   5138                                             unop(Iop_Not32,
   5139                                                  binop(Iop_Shl32,
   5140                                                        mkU32(0xffffffff),
   5141                                                        unop(Iop_32to8,
   5142                                                             mkexpr(t1))))),
   5143                                       unop(Iop_32to8,
   5144                                            mkexpr(t0))));
   5145 
   5146                      putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
   5147                                                   mkexpr(t0),
   5148                                                   mkU32(0)),
   5149                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   5150                                                              mkexpr(t1),
   5151                                                              mkU32(32)),
   5152                                                        getIReg(rs),
   5153                                                        binop(Iop_Or32,
   5154                                                              mkexpr(t6),
   5155                                                              mkexpr(t8))),
   5156                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   5157                                                              unop(Iop_8Uto32,
   5158                                                                   mkexpr(t2)),
   5159                                                              mkU32(32)),
   5160                                                        binop(Iop_Or32,
   5161                                                              mkexpr(t7),
   5162                                                              mkexpr(t8)),
   5163                                                        binop(Iop_Or32,
   5164                                                              binop(Iop_Or32,
   5165                                                                    mkexpr(t6),
   5166                                                                    mkexpr(t7)),
   5167                                                              mkexpr(t8)))));
   5168                      break;
   5169                   }
   5170                   default:
   5171                      return -1;
   5172                }
   5173                break;  /* enf of INSV */
   5174             }
   5175             case 0x10: {  /* ADDU.QB */
   5176                switch(sa) {
   5177                   case 0x00: {  /* ADDU.QB */
   5178                      DIP("addu.qb r%d, r%d, r%d", rd, rs, rt);
   5179                      vassert(!mode64);
   5180                      t0 = newTemp(Ity_I32);
   5181                      t1 = newTemp(Ity_I1);
   5182                      t2 = newTemp(Ity_I32);
   5183                      t3 = newTemp(Ity_I1);
   5184                      t4 = newTemp(Ity_I32);
   5185                      t5 = newTemp(Ity_I1);
   5186                      t6 = newTemp(Ity_I32);
   5187                      t7 = newTemp(Ity_I1);
   5188                      t8 = newTemp(Ity_I32);
   5189 
   5190                      /* Add rightmost bytes of rs and rt. */
   5191                      assign(t0,
   5192                             binop(Iop_Add32,
   5193                                   unop(Iop_8Uto32,
   5194                                        unop(Iop_16to8,
   5195                                             unop(Iop_32to16, getIReg(rs)))),
   5196                                   unop(Iop_8Uto32,
   5197                                        unop(Iop_16to8,
   5198                                             unop(Iop_32to16, getIReg(rt))))));
   5199                      /* t1 will be 1 if there is overflow, 0 otherwise. */
   5200                      assign(t1, binop(Iop_CmpEQ32,
   5201                                       binop(Iop_And32,
   5202                                             mkexpr(t0),
   5203                                             mkU32(0x00000100)),
   5204                                       mkU32(0x00000100)));
   5205 
   5206                      /* Add bits 15-8 of rs and rt. */
   5207                      assign(t2,
   5208                             binop(Iop_Add32,
   5209                                   unop(Iop_8Uto32,
   5210                                        unop(Iop_16HIto8,
   5211                                             unop(Iop_32to16, getIReg(rs)))),
   5212                                   unop(Iop_8Uto32,
   5213                                        unop(Iop_16HIto8,
   5214                                             unop(Iop_32to16, getIReg(rt))))));
   5215                      /* t3 will be 1 if there is overflow, 0 otherwise. */
   5216                      assign(t3, binop(Iop_CmpEQ32,
   5217                                       binop(Iop_And32,
   5218                                             mkexpr(t2),
   5219                                             mkU32(0x00000100)),
   5220                                       mkU32(0x00000100)));
   5221 
   5222                      /* Add bits 15-8 of rs and rt. */
   5223                      assign(t4,
   5224                             binop(Iop_Add32,
   5225                                   unop(Iop_8Uto32,
   5226                                        unop(Iop_16to8,
   5227                                             unop(Iop_32HIto16, getIReg(rs)))),
   5228                                   unop(Iop_8Uto32,
   5229                                        unop(Iop_16to8,
   5230                                             unop(Iop_32HIto16, getIReg(rt))))));
   5231                      /* t5 will be 1 if there is overflow, 0 otherwise. */
   5232                      assign(t5, binop(Iop_CmpEQ32,
   5233                                       binop(Iop_And32,
   5234                                             mkexpr(t4),
   5235                                             mkU32(0x00000100)),
   5236                                       mkU32(0x00000100)));
   5237 
   5238                      /* Add bits 15-8 of rs and rt. */
   5239                      assign(t6,
   5240                             binop(Iop_Add32,
   5241                                   unop(Iop_8Uto32,
   5242                                        unop(Iop_16HIto8,
   5243                                             unop(Iop_32HIto16, getIReg(rs)))),
   5244                                   unop(Iop_8Uto32,
   5245                                        unop(Iop_16HIto8,
   5246                                             unop(Iop_32HIto16, getIReg(rt))))));
   5247                      /* t7 will be 1 if there is overflow, 0 otherwise. */
   5248                      assign(t7, binop(Iop_CmpEQ32,
   5249                                       binop(Iop_And32,
   5250                                             mkexpr(t6),
   5251                                             mkU32(0x00000100)),
   5252                                       mkU32(0x00000100)));
   5253 
   5254                      assign(t8,
   5255                             binop(Iop_Or32,
   5256                                   binop(Iop_Or32,
   5257                                         binop(Iop_Or32,
   5258                                               unop(Iop_1Sto32, mkexpr(t7)),
   5259                                               unop(Iop_1Sto32,  mkexpr(t5))),
   5260                                         unop(Iop_1Sto32, mkexpr(t3))),
   5261                                   unop(Iop_1Sto32, mkexpr(t1))));
   5262 
   5263                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   5264                                                     mkexpr(t8),
   5265                                                     mkU32(0x0)),
   5266                                               getDSPControl(),
   5267                                               binop(Iop_Or32,
   5268                                                     getDSPControl(),
   5269                                                     mkU32(0x00100000))));
   5270 
   5271                      putIReg(rd, binop(Iop_16HLto32,
   5272                                        binop(Iop_8HLto16,
   5273                                              unop(Iop_32to8, mkexpr(t6)),
   5274                                              unop(Iop_32to8, mkexpr(t4))),
   5275                                        binop(Iop_8HLto16,
   5276                                              unop(Iop_32to8, mkexpr(t2)),
   5277                                              unop(Iop_32to8, mkexpr(t0)))));
   5278                      break;
   5279                   }
   5280                   case 0x1: {  /* SUBU.QB */
   5281                      DIP("subu.qb r%d, r%d, r%d", rd, rs, rt);
   5282                      vassert(!mode64);
   5283                      t0 = newTemp(Ity_I32);
   5284                      t1 = newTemp(Ity_I1);
   5285                      t2 = newTemp(Ity_I32);
   5286                      t3 = newTemp(Ity_I1);
   5287                      t4 = newTemp(Ity_I32);
   5288                      t5 = newTemp(Ity_I1);
   5289                      t6 = newTemp(Ity_I32);
   5290                      t7 = newTemp(Ity_I1);
   5291                      t8 = newTemp(Ity_I32);
   5292 
   5293                      /* Subtract rightmost bytes of rs and rt. */
   5294                      assign(t0,
   5295                             binop(Iop_Sub32,
   5296                                   unop(Iop_8Uto32,
   5297                                        unop(Iop_16to8,
   5298                                             unop(Iop_32to16, getIReg(rs)))),
   5299                                   unop(Iop_8Uto32,
   5300                                        unop(Iop_16to8,
   5301                                             unop(Iop_32to16, getIReg(rt))))));
   5302                      /* t1 will be 1 if there is overflow, 0 otherwise. */
   5303                      assign(t1, binop(Iop_CmpEQ32,
   5304                                       binop(Iop_And32,
   5305                                             mkexpr(t0),
   5306                                             mkU32(0x00000100)),
   5307                                       mkU32(0x00000100)));
   5308 
   5309                      /* Subtract bits 15-8 of rs and rt. */
   5310                      assign(t2,
   5311                             binop(Iop_Sub32,
   5312                                   unop(Iop_8Uto32,
   5313                                        unop(Iop_16HIto8,
   5314                                             unop(Iop_32to16, getIReg(rs)))),
   5315                                   unop(Iop_8Uto32,
   5316                                        unop(Iop_16HIto8,
   5317                                             unop(Iop_32to16, getIReg(rt))))));
   5318                      /* t3 will be 1 if there is overflow, 0 otherwise. */
   5319                      assign(t3, binop(Iop_CmpEQ32,
   5320                                       binop(Iop_And32,
   5321                                             mkexpr(t2),
   5322                                             mkU32(0x00000100)),
   5323                                       mkU32(0x00000100)));
   5324 
   5325                      /* Subtract bits 15-8 of rs and rt. */
   5326                      assign(t4,
   5327                             binop(Iop_Sub32,
   5328                                   unop(Iop_8Uto32,
   5329                                        unop(Iop_16to8,
   5330                                             unop(Iop_32HIto16, getIReg(rs)))),
   5331                                   unop(Iop_8Uto32,
   5332                                        unop(Iop_16to8,
   5333                                             unop(Iop_32HIto16, getIReg(rt))))));
   5334                      /* t5 will be 1 if there is overflow, 0 otherwise. */
   5335                      assign(t5, binop(Iop_CmpEQ32,
   5336                                       binop(Iop_And32,
   5337                                             mkexpr(t4),
   5338                                             mkU32(0x00000100)),
   5339                                       mkU32(0x00000100)));
   5340 
   5341                      /* Subtract bits 15-8 of rs and rt. */
   5342                      assign(t6,
   5343                             binop(Iop_Sub32,
   5344                                   unop(Iop_8Uto32,
   5345                                        unop(Iop_16HIto8,
   5346                                             unop(Iop_32HIto16, getIReg(rs)))),
   5347                                   unop(Iop_8Uto32,
   5348                                        unop(Iop_16HIto8,
   5349                                             unop(Iop_32HIto16, getIReg(rt))))));
   5350                      /* t7 will be 1 if there is overflow, 0 otherwise. */
   5351                      assign(t7, binop(Iop_CmpEQ32,
   5352                                       binop(Iop_And32,
   5353                                             mkexpr(t6),
   5354                                             mkU32(0x00000100)),
   5355                                       mkU32(0x00000100)));
   5356 
   5357                      assign(t8, binop(Iop_Or32,
   5358                                       binop(Iop_Or32,
   5359                                             binop(Iop_Or32,
   5360                                                   unop(Iop_1Sto32, mkexpr(t7)),
   5361                                                   unop(Iop_1Sto32, mkexpr(t5))),
   5362                                             unop(Iop_1Sto32, mkexpr(t3))),
   5363                                       unop(Iop_1Sto32, mkexpr(t1))));
   5364 
   5365                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   5366                                                      mkexpr(t8),
   5367                                                      mkU32(0x0)),
   5368                                               getDSPControl(),
   5369                                               binop(Iop_Or32,
   5370                                                     getDSPControl(),
   5371                                                     mkU32(0x00100000))));
   5372 
   5373                      putIReg(rd, binop(Iop_16HLto32,
   5374                                        binop(Iop_8HLto16,
   5375                                              unop(Iop_32to8, mkexpr(t6)),
   5376                                              unop(Iop_32to8, mkexpr(t4))),
   5377                                        binop(Iop_8HLto16,
   5378                                              unop(Iop_32to8, mkexpr(t2)),
   5379                                              unop(Iop_32to8, mkexpr(t0)))));
   5380                      break;
   5381                   }
   5382                   case 0x04: {  /* ADDU_S.QB */
   5383                      DIP("addu_s.qb r%d, r%d, r%d", rd, rs, rt);
   5384                      vassert(!mode64);
   5385                      t0 = newTemp(Ity_I32);
   5386                      t1 = newTemp(Ity_I1);
   5387                      t2 = newTemp(Ity_I8);
   5388                      t3 = newTemp(Ity_I32);
   5389                      t4 = newTemp(Ity_I1);
   5390                      t5 = newTemp(Ity_I8);
   5391                      t6 = newTemp(Ity_I32);
   5392                      t7 = newTemp(Ity_I1);
   5393                      t8 = newTemp(Ity_I8);
   5394                      t9 = newTemp(Ity_I32);
   5395                      t10 = newTemp(Ity_I1);
   5396                      t11 = newTemp(Ity_I8);
   5397                      t12 = newTemp(Ity_I32);
   5398 
   5399                      /* Add rightmost bytes of rs and rt. */
   5400                      assign(t0,
   5401                             binop(Iop_Add32,
   5402                                   unop(Iop_8Uto32,
   5403                                        unop(Iop_16to8,
   5404                                             unop(Iop_32to16, getIReg(rs)))),
   5405                                   unop(Iop_8Uto32,
   5406                                        unop(Iop_16to8,
   5407                                             unop(Iop_32to16, getIReg(rt))))));
   5408                      /* t1 will be 1 if there is overflow, 0 otherwise. */
   5409                      assign(t1, binop(Iop_CmpEQ32,
   5410                                       binop(Iop_And32,
   5411                                             mkexpr(t0),
   5412                                             mkU32(0x00000100)),
   5413                                       mkU32(0x00000100)));
   5414                      /* Saturate if necessary. */
   5415                      assign(t2, IRExpr_ITE(mkexpr(t1),
   5416                                            mkU8(0xff),
   5417                                            unop(Iop_32to8, mkexpr(t0))));
   5418 
   5419                      /* Add bits 15-8 of rs and rt. */
   5420                      assign(t3,
   5421                             binop(Iop_Add32,
   5422                                   unop(Iop_8Uto32,
   5423                                        unop(Iop_16HIto8,
   5424                                             unop(Iop_32to16, getIReg(rs)))),
   5425                                   unop(Iop_8Uto32,
   5426                                        unop(Iop_16HIto8,
   5427                                             unop(Iop_32to16, getIReg(rt))))));
   5428                      /* t4 will be 1 if there is overflow, 0 otherwise. */
   5429                      assign(t4, binop(Iop_CmpEQ32,
   5430                                       binop(Iop_And32,
   5431                                             mkexpr(t3),
   5432                                             mkU32(0x00000100)),
   5433                                       mkU32(0x00000100)));
   5434                      /* Saturate if necessary. */
   5435                      assign(t5, IRExpr_ITE(mkexpr(t4),
   5436                                            mkU8(0xff),
   5437                                            unop(Iop_32to8, mkexpr(t3))));
   5438 
   5439                      /* Add bits 15-8 of rs and rt. */
   5440                      assign(t6,
   5441                             binop(Iop_Add32,
   5442                                   unop(Iop_8Uto32,
   5443                                        unop(Iop_16to8,
   5444                                             unop(Iop_32HIto16, getIReg(rs)))),
   5445                                   unop(Iop_8Uto32,
   5446                                        unop(Iop_16to8,
   5447                                             unop(Iop_32HIto16, getIReg(rt))))));
   5448                      /* t7 will be 1 if there is overflow, 0 otherwise. */
   5449                      assign(t7, binop(Iop_CmpEQ32,
   5450                                       binop(Iop_And32,
   5451                                             mkexpr(t6),
   5452                                             mkU32(0x00000100)),
   5453                                       mkU32(0x00000100)));
   5454                      /* Saturate if necessary. */
   5455                      assign(t8, IRExpr_ITE(mkexpr(t7),
   5456                                            mkU8(0xff),
   5457                                            unop(Iop_32to8, mkexpr(t6))));
   5458 
   5459                      /* Add bits 15-8 of rs and rt. */
   5460                      assign(t9,
   5461                             binop(Iop_Add32,
   5462                                   unop(Iop_8Uto32,
   5463                                        unop(Iop_16HIto8,
   5464                                             unop(Iop_32HIto16, getIReg(rs)))),
   5465                                   unop(Iop_8Uto32,
   5466                                        unop(Iop_16HIto8,
   5467                                             unop(Iop_32HIto16, getIReg(rt))))));
   5468                      /* t10 will be 1 if there is overflow, 0 otherwise. */
   5469                      assign(t10, binop(Iop_CmpEQ32,
   5470                                        binop(Iop_And32,
   5471                                              mkexpr(t9),
   5472                                              mkU32(0x00000100)),
   5473                                        mkU32(0x00000100)));
   5474                      /* Saturate if necessary. */
   5475                      assign(t11, IRExpr_ITE(mkexpr(t10),
   5476                                             mkU8(0xff),
   5477                                             unop(Iop_32to8, mkexpr(t9))));
   5478 
   5479                      assign(t12,
   5480                             binop(Iop_Or32,
   5481                                   binop(Iop_Or32,
   5482                                         binop(Iop_Or32,
   5483                                               unop(Iop_1Sto32, mkexpr(t10)),
   5484                                               unop(Iop_1Sto32, mkexpr(t7))),
   5485                                         unop(Iop_1Sto32, mkexpr(t4))),
   5486                                   unop(Iop_1Sto32, mkexpr(t1))));
   5487 
   5488                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   5489                                                     mkexpr(t12),
   5490                                                     mkU32(0x0)),
   5491                                               getDSPControl(),
   5492                                               binop(Iop_Or32,
   5493                                                     getDSPControl(),
   5494                                                     mkU32(0x00100000))));
   5495 
   5496                      putIReg(rd,
   5497                              binop(Iop_16HLto32,
   5498                                    binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
   5499                                    binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
   5500                      break;
   5501                   }
   5502                   case 0x05: {  /* SUBU_S.QB */
   5503                      DIP("subu_s.qb r%d, r%d, r%d", rd, rs, rt);
   5504                      vassert(!mode64);
   5505                      t1 = newTemp(Ity_I32);
   5506                      t2 = newTemp(Ity_I1);
   5507                      t3 = newTemp(Ity_I1);
   5508                      t4 = newTemp(Ity_I1);
   5509                      t5 = newTemp(Ity_I1);
   5510                      t6 = newTemp(Ity_I32);
   5511                      t7 = newTemp(Ity_I32);
   5512                      t8 = newTemp(Ity_I32);
   5513                      t9 = newTemp(Ity_I32);
   5514 
   5515                      /* Use C function to easily calculate the result
   5516                         and write it in the register more conveniently
   5517                         Underflow is checked using step by step subtraction. */
   5518                      assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
   5519 
   5520                      /* Subtract each byte of rs and rt. */
   5521                      assign(t6,
   5522                             binop(Iop_Sub32,
   5523                                   unop(Iop_8Uto32,
   5524                                        unop(Iop_16to8,
   5525                                             unop(Iop_32to16, getIReg(rs)))),
   5526                                   unop(Iop_8Uto32,
   5527                                        unop(Iop_16to8,
   5528                                             unop(Iop_32to16, getIReg(rt))))));
   5529                      assign(t7,
   5530                             binop(Iop_Sub32,
   5531                                   unop(Iop_8Uto32,
   5532                                        unop(Iop_16HIto8,
   5533                                             unop(Iop_32to16, getIReg(rs)))),
   5534                                   unop(Iop_8Uto32,
   5535                                        unop(Iop_16HIto8,
   5536                                             unop(Iop_32to16, getIReg(rt))))));
   5537                      assign(t8,
   5538                             binop(Iop_Sub32,
   5539                                   unop(Iop_8Uto32,
   5540                                        unop(Iop_16to8,
   5541                                             unop(Iop_32HIto16, getIReg(rs)))),
   5542                                   unop(Iop_8Uto32,
   5543                                        unop(Iop_16to8,
   5544                                             unop(Iop_32HIto16, getIReg(rt))))));
   5545                      assign(t9,
   5546                             binop(Iop_Sub32,
   5547                                   unop(Iop_8Uto32,
   5548                                        unop(Iop_16HIto8,
   5549                                             unop(Iop_32HIto16, getIReg(rs)))),
   5550                                   unop(Iop_8Uto32,
   5551                                        unop(Iop_16HIto8,
   5552                                             unop(Iop_32HIto16, getIReg(rt))))));
   5553 
   5554                      /* Put 1 to bit 20 in DSPControl if there is underflow
   5555                         in either byte. */
   5556                      assign(t2, binop(Iop_CmpEQ32,
   5557                                       binop(Iop_And32,
   5558                                             mkexpr(t6),
   5559                                             mkU32(0x00000100)),
   5560                                       mkU32(0x00000100)));
   5561                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   5562                                               binop(Iop_Or32,
   5563                                                     getDSPControl(),
   5564                                                     mkU32(0x00100000)),
   5565                                               getDSPControl()));
   5566                      assign(t3, binop(Iop_CmpEQ32,
   5567                                       binop(Iop_And32,
   5568                                             mkexpr(t7),
   5569                                             mkU32(0x00000100)),
   5570                                       mkU32(0x00000100)));
   5571                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   5572                                               binop(Iop_Or32,
   5573                                                     getDSPControl(),
   5574                                                     mkU32(0x00100000)),
   5575                                               getDSPControl()));
   5576                      assign(t4, binop(Iop_CmpEQ32,
   5577                                       binop(Iop_And32,
   5578                                             mkexpr(t8),
   5579                                             mkU32(0x00000100)),
   5580                                       mkU32(0x00000100)));
   5581                      putDSPControl(IRExpr_ITE(mkexpr(t4),
   5582                                               binop(Iop_Or32,
   5583                                                     getDSPControl(),
   5584                                                     mkU32(0x00100000)),
   5585                                               getDSPControl()));
   5586                      assign(t5, binop(Iop_CmpEQ32,
   5587                                       binop(Iop_And32,
   5588                                             mkexpr(t9),
   5589                                             mkU32(0x00000100)),
   5590                                       mkU32(0x00000100)));
   5591                      putDSPControl(IRExpr_ITE(mkexpr(t5),
   5592                                               binop(Iop_Or32,
   5593                                                     getDSPControl(),
   5594                                                     mkU32(0x00100000)),
   5595                                               getDSPControl()));
   5596                      putIReg(rd, mkexpr(t1));
   5597                      break;
   5598                   }
   5599                   case 0x6: {  /* MULEU_S.PH.QBL */
   5600                      DIP("muleu_s.ph.qbl r%d, r%d, r%d", rd, rs, rt);
   5601                      vassert(!mode64);
   5602                      t0 = newTemp(Ity_I32);
   5603                      t1 = newTemp(Ity_I32);
   5604                      t2 = newTemp(Ity_I1);
   5605                      t3 = newTemp(Ity_I1);
   5606 
   5607                      assign(t0,
   5608                             unop(Iop_64to32,
   5609                                  binop(Iop_MullU32,
   5610                                        unop(Iop_8Uto32,
   5611                                             unop(Iop_16HIto8,
   5612                                                  unop(Iop_32HIto16,
   5613                                                       getIReg(rs)))),
   5614                                        unop(Iop_16Uto32,
   5615                                             unop(Iop_32HIto16, getIReg(rt))))));
   5616                      assign(t1,
   5617                             unop(Iop_64to32,
   5618                                  binop(Iop_MullU32,
   5619                                        unop(Iop_8Uto32,
   5620                                             unop(Iop_16to8,
   5621                                                  unop(Iop_32HIto16,
   5622                                                       getIReg(rs)))),
   5623                                        unop(Iop_16Uto32,
   5624                                             unop(Iop_32to16, getIReg(rt))))));
   5625 
   5626                      assign(t2, binop(Iop_CmpNE32,
   5627                                       mkU32(0x0),
   5628                                       binop(Iop_And32,
   5629                                             mkexpr(t0),
   5630                                             mkU32(0x03ff0000))));
   5631                      assign(t3, binop(Iop_CmpNE32,
   5632                                       mkU32(0x0),
   5633                                       binop(Iop_And32,
   5634                                             mkexpr(t1),
   5635                                             mkU32(0x03ff0000))));
   5636                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   5637                                               binop(Iop_Or32,
   5638                                                     getDSPControl(),
   5639                                                     mkU32(0x200000)),
   5640                                               IRExpr_ITE(mkexpr(t3),
   5641                                                          binop(Iop_Or32,
   5642                                                                getDSPControl(),
   5643                                                                mkU32(0x200000)),
   5644                                                          getDSPControl())));
   5645                      putIReg(rd,
   5646                              binop(Iop_16HLto32,
   5647                                    IRExpr_ITE(mkexpr(t2),
   5648                                               mkU16(0xffff),
   5649                                               unop(Iop_32to16, mkexpr(t0))),
   5650                                    IRExpr_ITE(mkexpr(t3),
   5651                                               mkU16(0xffff),
   5652                                               unop(Iop_32to16, mkexpr(t1)))));
   5653                      break;
   5654                   }
   5655                   case 0x7: {  /* MULEU_S.PH.QBR */
   5656                      DIP("muleu_s.ph.qbr r%d, r%d, r%d", rd, rs, rt);
   5657                      vassert(!mode64);
   5658                      t0 = newTemp(Ity_I32);
   5659                      t1 = newTemp(Ity_I32);
   5660                      t2 = newTemp(Ity_I1);
   5661                      t3 = newTemp(Ity_I1);
   5662 
   5663                      assign(t0, unop(Iop_64to32,
   5664                                      binop(Iop_MullU32,
   5665                                            unop(Iop_8Uto32,
   5666                                                 unop(Iop_16HIto8,
   5667                                                      unop(Iop_32to16,
   5668                                                           getIReg(rs)))),
   5669                                            unop(Iop_16Uto32,
   5670                                                 unop(Iop_32HIto16,
   5671                                                      getIReg(rt))))));
   5672                      assign(t1, unop(Iop_64to32,
   5673                                      binop(Iop_MullU32,
   5674                                            unop(Iop_8Uto32,
   5675                                                 unop(Iop_16to8,
   5676                                                      unop(Iop_32to16,
   5677                                                           getIReg(rs)))),
   5678                                            unop(Iop_16Uto32,
   5679                                                 unop(Iop_32to16,
   5680                                                      getIReg(rt))))));
   5681 
   5682                      assign(t2, binop(Iop_CmpNE32,
   5683                                       mkU32(0x0),
   5684                                       binop(Iop_And32,
   5685                                             mkexpr(t0),
   5686                                             mkU32(0x03ff0000))));
   5687                      assign(t3, binop(Iop_CmpNE32,
   5688                                       mkU32(0x0),
   5689                                       binop(Iop_And32,
   5690                                             mkexpr(t1),
   5691                                             mkU32(0x03ff0000))));
   5692                      putDSPControl(IRExpr_ITE(mkexpr(t2),
   5693                                               binop(Iop_Or32,
   5694                                                     getDSPControl(),
   5695                                                     mkU32(0x200000)),
   5696                                               IRExpr_ITE(mkexpr(t3),
   5697                                                          binop(Iop_Or32,
   5698                                                                getDSPControl(),
   5699                                                                mkU32(0x200000)),
   5700                                                          getDSPControl())));
   5701                      putIReg(rd, binop(Iop_16HLto32,
   5702                                        IRExpr_ITE(mkexpr(t2),
   5703                                                   mkU16(0xffff),
   5704                                                   unop(Iop_32to16,
   5705                                                        mkexpr(t0))),
   5706                                        IRExpr_ITE(mkexpr(t3),
   5707                                                   mkU16(0xffff),
   5708                                                   unop(Iop_32to16,
   5709                                                        mkexpr(t1)))));
   5710                      break;
   5711                   }
   5712                   case 0x08: {  /* ADDU.PH */
   5713                      DIP("addu.ph r%d, r%d, r%d", rd, rs, rt);
   5714                      vassert(!mode64);
   5715                      t0 = newTemp(Ity_I32);
   5716                      t1 = newTemp(Ity_I1);
   5717                      t2 = newTemp(Ity_I32);
   5718                      t3 = newTemp(Ity_I1);
   5719 
   5720                      /* Add lower halves. */
   5721                      assign(t0, binop(Iop_Add32,
   5722                                       unop(Iop_16Uto32,
   5723                                            unop(Iop_32to16, getIReg(rs))),
   5724                                       unop(Iop_16Uto32,
   5725                                            unop(Iop_32to16, getIReg(rt)))));
   5726 
   5727                      /* Detect overflow. */
   5728                      assign(t1, binop(Iop_CmpLT32U,
   5729                                       unop(Iop_16Uto32,
   5730                                            unop(Iop_32to16, mkexpr(t0))),
   5731                                       unop(Iop_16Uto32,
   5732                                            unop(Iop_32to16, getIReg(rs)))));
   5733 
   5734                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   5735                                               binop(Iop_Or32,
   5736                                                     getDSPControl(),
   5737                                                     mkU32(0x00100000)),
   5738                                               getDSPControl()));
   5739 
   5740                      /* Add higher halves. */
   5741                      assign(t2, binop(Iop_Add32,
   5742                                       unop(Iop_16Uto32,
   5743                                            unop(Iop_32HIto16, getIReg(rs))),
   5744                                       unop(Iop_16Uto32,
   5745                                            unop(Iop_32HIto16, getIReg(rt)))));
   5746 
   5747                      /* Detect overflow. */
   5748                      assign(t3, binop(Iop_CmpLT32U,
   5749                                       unop(Iop_16Uto32,
   5750                                            unop(Iop_32to16, mkexpr(t2))),
   5751                                       unop(Iop_16Uto32,
   5752                                            unop(Iop_32HIto16,
   5753                                                 getIReg(rs)))));
   5754 
   5755                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   5756                                               binop(Iop_Or32,
   5757                                                     getDSPControl(),
   5758                                                     mkU32(0x00100000)),
   5759                                               getDSPControl()));
   5760 
   5761                      putIReg(rd, binop(Iop_16HLto32,
   5762                                        unop(Iop_32to16, mkexpr(t2)),
   5763                                        unop(Iop_32to16, mkexpr(t0))));
   5764                      break;
   5765                   }
   5766                   case 0x9: {  /* SUBU.PH */
   5767                      DIP("subu.ph r%d, r%d, r%d", rd, rs, rt);
   5768                      vassert(!mode64);
   5769                      t0 = newTemp(Ity_I32);
   5770                      t1 = newTemp(Ity_I1);
   5771                      t2 = newTemp(Ity_I32);
   5772                      t3 = newTemp(Ity_I1);
   5773 
   5774                      /* Substract lower halves. */
   5775                      assign(t0, binop(Iop_Sub32,
   5776                                       unop(Iop_16Uto32,
   5777                                            unop(Iop_32to16, getIReg(rs))),
   5778                                       unop(Iop_16Uto32,
   5779                                            unop(Iop_32to16, getIReg(rt)))));
   5780 
   5781                      /* Detect underflow. */
   5782                      assign(t1, binop(Iop_CmpNE32,
   5783                                       binop(Iop_And32,
   5784                                             mkexpr(t0),
   5785                                             mkU32(0x00010000)),
   5786                                       mkU32(0x0)));
   5787 
   5788                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   5789                                               binop(Iop_Or32,
   5790                                                     getDSPControl(),
   5791                                                     mkU32(0x00100000)),
   5792                                               getDSPControl()));
   5793 
   5794                      /* Subtract higher halves. */
   5795                      assign(t2, binop(Iop_Sub32,
   5796                                       unop(Iop_16Uto32,
   5797                                            unop(Iop_32HIto16, getIReg(rs))),
   5798                                       unop(Iop_16Uto32,
   5799                                            unop(Iop_32HIto16, getIReg(rt)))));
   5800 
   5801                      /* Detect underflow. */
   5802                      assign(t3, binop(Iop_CmpNE32,
   5803                                       binop(Iop_And32,
   5804                                             mkexpr(t2),
   5805                                             mkU32(0x00010000)),
   5806                                       mkU32(0x0)));
   5807 
   5808                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   5809                                               binop(Iop_Or32,
   5810                                                     getDSPControl(),
   5811                                                     mkU32(0x00100000)),
   5812                                               getDSPControl()));
   5813 
   5814                      putIReg(rd, binop(Iop_16HLto32,
   5815                                        unop(Iop_32to16, mkexpr(t2)),
   5816                                        unop(Iop_32to16, mkexpr(t0))));
   5817                      break;
   5818                   }
   5819                   case 0xA: {  /* ADDQ.PH */
   5820                      DIP("addq.ph r%d, r%d, r%d", rd, rs, rt);
   5821                      vassert(!mode64);
   5822                      t0 = newTemp(Ity_I32);
   5823                      t1 = newTemp(Ity_I1);
   5824                      t2 = newTemp(Ity_I32);
   5825                      t3 = newTemp(Ity_I1);
   5826                      t6 = newTemp(Ity_I32);
   5827                      t7 = newTemp(Ity_I32);
   5828 
   5829                      /* Add lower halves. */
   5830                      assign(t0, binop(Iop_Add32,
   5831                                       unop(Iop_16Sto32,
   5832                                            unop(Iop_32to16, getIReg(rs))),
   5833                                       unop(Iop_16Sto32,
   5834                                            unop(Iop_32to16, getIReg(rt)))));
   5835 
   5836                      /* Bit 16 of the result. */
   5837                      assign(t6, binop(Iop_And32,
   5838                                       unop(Iop_16Uto32,
   5839                                            unop(Iop_32HIto16, mkexpr(t0))),
   5840                                       mkU32(0x1)));
   5841                      /* Detect overflow. */
   5842                      assign(t1, binop(Iop_CmpNE32,
   5843                                       binop(Iop_Shr32,
   5844                                             binop(Iop_And32,
   5845                                                   mkexpr(t0),
   5846                                                   mkU32(0x8000)),
   5847                                             mkU8(15)),
   5848                                       mkexpr(t6)));
   5849 
   5850                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   5851                                               binop(Iop_Or32,
   5852                                                     getDSPControl(),
   5853                                                     mkU32(0x00100000)),
   5854                                               getDSPControl()));
   5855 
   5856                      /* Add higher halves. */
   5857                      assign(t2, binop(Iop_Add32,
   5858                                       unop(Iop_16Sto32,
   5859                                            unop(Iop_32HIto16, getIReg(rs))),
   5860                                       unop(Iop_16Sto32,
   5861                                            unop(Iop_32HIto16, getIReg(rt)))));
   5862 
   5863                      /* Bit 16 of the result. */
   5864                      assign(t7, binop(Iop_And32,
   5865                                       unop(Iop_16Uto32,
   5866                                            unop(Iop_32HIto16, mkexpr(t2))),
   5867                                       mkU32(0x1)));
   5868                      /* Detect overflow. */
   5869                      assign(t3, binop(Iop_CmpNE32,
   5870                                       binop(Iop_Shr32,
   5871                                             binop(Iop_And32,
   5872                                                   mkexpr(t2),
   5873                                                   mkU32(0x00008000)),
   5874                                             mkU8(15)),
   5875                                       mkexpr(t7)));
   5876 
   5877                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   5878                                               binop(Iop_Or32,
   5879                                                     getDSPControl(),
   5880                                                     mkU32(0x00100000)),
   5881                                               getDSPControl()));
   5882 
   5883                      putIReg(rd, binop(Iop_16HLto32,
   5884                                        unop(Iop_32to16, mkexpr(t2)),
   5885                                        unop(Iop_32to16, mkexpr(t0))));
   5886                      break;
   5887                   }
   5888                   case 0xB: {  /* SUBQ.PH */
   5889                      DIP("subq.ph r%d, r%d, r%d", rd, rs, rt);
   5890                      vassert(!mode64);
   5891                      t0 = newTemp(Ity_I32);
   5892                      t1 = newTemp(Ity_I1);
   5893                      t2 = newTemp(Ity_I32);
   5894                      t3 = newTemp(Ity_I1);
   5895                      t6 = newTemp(Ity_I32);
   5896                      t7 = newTemp(Ity_I32);
   5897 
   5898                      /* Subtract lower halves. */
   5899                      assign(t0, binop(Iop_Sub32,
   5900                                       unop(Iop_16Sto32,
   5901                                            unop(Iop_32to16, getIReg(rs))),
   5902                                       unop(Iop_16Sto32,
   5903                                            unop(Iop_32to16, getIReg(rt)))));
   5904 
   5905                      /* Bit 16 of the result. */
   5906                      assign(t6, binop(Iop_And32,
   5907                                       unop(Iop_16Uto32,
   5908                                            unop(Iop_32HIto16, mkexpr(t0))),
   5909                                       mkU32(0x1)));
   5910                      /* Compare the signs of input value and the result. */
   5911                      assign(t1, binop(Iop_CmpNE32,
   5912                                       binop(Iop_Shr32,
   5913                                             binop(Iop_And32,
   5914                                                   mkexpr(t0),
   5915                                                   mkU32(0x8000)),
   5916                                             mkU8(15)),
   5917                                       mkexpr(t6)));
   5918 
   5919                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   5920                                               binop(Iop_Or32,
   5921                                                     getDSPControl(),
   5922                                                     mkU32(0x00100000)),
   5923                                               getDSPControl()));
   5924 
   5925                      /* Subtract higher halves. */
   5926                      assign(t2, binop(Iop_Sub32,
   5927                                       unop(Iop_16Sto32,
   5928                                            unop(Iop_32HIto16, getIReg(rs))),
   5929                                       unop(Iop_16Sto32,
   5930                                            unop(Iop_32HIto16, getIReg(rt)))));
   5931 
   5932                      /* Bit 16 of the result. */
   5933                      assign(t7, binop(Iop_And32,
   5934                                       unop(Iop_16Uto32,
   5935                                            unop(Iop_32HIto16, mkexpr(t2))),
   5936                                       mkU32(0x1)));
   5937                      /* Compare the signs of input value and the result. */
   5938                      assign(t3, binop(Iop_CmpNE32,
   5939                                       binop(Iop_Shr32,
   5940                                             binop(Iop_And32,
   5941                                                   mkexpr(t2),
   5942                                                   mkU32(0x00008000)),
   5943                                             mkU8(15)),
   5944                                       mkexpr(t7)));
   5945 
   5946                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   5947                                               binop(Iop_Or32,
   5948                                                     getDSPControl(),
   5949                                                     mkU32(0x00100000)),
   5950                                               getDSPControl()));
   5951 
   5952                      putIReg(rd, binop(Iop_16HLto32,
   5953                                        unop(Iop_32to16, mkexpr(t2)),
   5954                                        unop(Iop_32to16, mkexpr(t0))));
   5955                      break;
   5956                   }
   5957                   case 0xC: {  /* ADDU_S.PH */
   5958                      DIP("addu_s.ph r%d, r%d, r%d", rd, rs, rt);
   5959                      vassert(!mode64);
   5960                      t0 = newTemp(Ity_I32);
   5961                      t1 = newTemp(Ity_I1);
   5962                      t2 = newTemp(Ity_I32);
   5963                      t3 = newTemp(Ity_I1);
   5964 
   5965                      /* Add lower halves. */
   5966                      assign(t0, binop(Iop_Add32,
   5967                                       unop(Iop_16Uto32,
   5968                                            unop(Iop_32to16, getIReg(rs))),
   5969                                       unop(Iop_16Uto32,
   5970                                            unop(Iop_32to16, getIReg(rt)))));
   5971 
   5972                      /* Detect overflow. */
   5973                      assign(t1, binop(Iop_CmpLT32U,
   5974                                       unop(Iop_16Uto32,
   5975                                            unop(Iop_32to16, mkexpr(t0))),
   5976                                       unop(Iop_16Uto32,
   5977                                            unop(Iop_32to16, getIReg(rs)))));
   5978 
   5979                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   5980                                               binop(Iop_Or32,
   5981                                                     getDSPControl(),
   5982                                                     mkU32(0x00100000)),
   5983                                               getDSPControl()));
   5984 
   5985                      /* Add higher halves. */
   5986                      assign(t2, binop(Iop_Add32,
   5987                                       unop(Iop_16Uto32,
   5988                                            unop(Iop_32HIto16, getIReg(rs))),
   5989                                       unop(Iop_16Uto32,
   5990                                            unop(Iop_32HIto16, getIReg(rt)))));
   5991 
   5992                      /* Detect overflow. */
   5993                      assign(t3, binop(Iop_CmpLT32U,
   5994                                       unop(Iop_16Uto32,
   5995                                            unop(Iop_32to16, mkexpr(t2))),
   5996                                       unop(Iop_16Uto32,
   5997                                            unop(Iop_32HIto16, getIReg(rs)))));
   5998 
   5999                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   6000                                               binop(Iop_Or32,
   6001                                                     getDSPControl(),
   6002                                                     mkU32(0x00100000)),
   6003                                               getDSPControl()));
   6004 
   6005                      putIReg(rd, binop(Iop_16HLto32,
   6006                                        IRExpr_ITE(mkexpr(t3),
   6007                                                   mkU16(0xffff),
   6008                                                   unop(Iop_32to16,
   6009                                                        mkexpr(t2))),
   6010                                        IRExpr_ITE(mkexpr(t1),
   6011                                                   mkU16(0xffff),
   6012                                                   unop(Iop_32to16,
   6013                                                        mkexpr(t0)))));
   6014                      break;
   6015                   }
   6016                   case 0xD: {  /* SUBU_S.PH */
   6017                      DIP("subu_s.ph r%d, r%d, r%d", rd, rs, rt);
   6018                      vassert(!mode64);
   6019                      t0 = newTemp(Ity_I32);
   6020                      t1 = newTemp(Ity_I1);
   6021                      t2 = newTemp(Ity_I32);
   6022                      t3 = newTemp(Ity_I1);
   6023 
   6024                      /* Subtract lower halves. */
   6025                      assign(t0, binop(Iop_Sub32,
   6026                                       unop(Iop_16Uto32,
   6027                                            unop(Iop_32to16, getIReg(rs))),
   6028                                       unop(Iop_16Uto32,
   6029                                            unop(Iop_32to16, getIReg(rt)))));
   6030 
   6031                      /* Detect underflow. */
   6032                      assign(t1, binop(Iop_CmpNE32,
   6033                                       binop(Iop_And32,
   6034                                             mkexpr(t0), mkU32(0x00010000)),
   6035                                       mkU32(0x0)));
   6036 
   6037                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6038                                               binop(Iop_Or32,
   6039                                                     getDSPControl(),
   6040                                                     mkU32(0x00100000)),
   6041                                               getDSPControl()));
   6042 
   6043                      /* Subtract higher halves. */
   6044                      assign(t2, binop(Iop_Sub32,
   6045                                       unop(Iop_16Uto32,
   6046                                            unop(Iop_32HIto16, getIReg(rs))),
   6047                                       unop(Iop_16Uto32,
   6048                                            unop(Iop_32HIto16, getIReg(rt)))));
   6049 
   6050                      /* Detect underflow. */
   6051                      assign(t3, binop(Iop_CmpNE32,
   6052                                       binop(Iop_And32,
   6053                                             mkexpr(t2), mkU32(0x00010000)),
   6054                                       mkU32(0x0)));
   6055 
   6056                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   6057                                               binop(Iop_Or32,
   6058                                                     getDSPControl(),
   6059                                                     mkU32(0x00100000)),
   6060                                               getDSPControl()));
   6061 
   6062                      putIReg(rd,
   6063                              binop(Iop_16HLto32,
   6064                                    IRExpr_ITE(mkexpr(t3),
   6065                                               mkU16(0x0000),
   6066                                               unop(Iop_32to16, mkexpr(t2))),
   6067                                    IRExpr_ITE(mkexpr(t1),
   6068                                               mkU16(0x0000),
   6069                                               unop(Iop_32to16, mkexpr(t0)))));
   6070                      break;
   6071                   }
   6072                   case 0xE: {  /* ADDQ_S.PH */
   6073                      DIP("addq_s.ph r%d r%d, r%d", rd, rs, rt);
   6074                      vassert(!mode64);
   6075                      t0 = newTemp(Ity_I32);
   6076                      t1 = newTemp(Ity_I1);
   6077                      t2 = newTemp(Ity_I32);
   6078                      t3 = newTemp(Ity_I1);
   6079                      t4 = newTemp(Ity_I16);
   6080                      t5 = newTemp(Ity_I16);
   6081                      t6 = newTemp(Ity_I32);
   6082                      t7 = newTemp(Ity_I32);
   6083 
   6084                      /* Add lower halves. */
   6085                      assign(t0, binop(Iop_Add32,
   6086                                       unop(Iop_16Sto32,
   6087                                            unop(Iop_32to16, getIReg(rs))),
   6088                                       unop(Iop_16Sto32,
   6089                                            unop(Iop_32to16, getIReg(rt)))));
   6090 
   6091                      /* Bit 16 of the result. */
   6092                      assign(t6, binop(Iop_And32,
   6093                                       unop(Iop_16Uto32,
   6094                                            unop(Iop_32HIto16, mkexpr(t0))),
   6095                                       mkU32(0x1)));
   6096                      /* Detect overflow. */
   6097                      assign(t1, binop(Iop_CmpNE32,
   6098                                       binop(Iop_Shr32,
   6099                                             binop(Iop_And32,
   6100                                                   mkexpr(t0),
   6101                                                   mkU32(0x8000)),
   6102                                             mkU8(15)),
   6103                                       mkexpr(t6)));
   6104 
   6105                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6106                                               binop(Iop_Or32,
   6107                                                     getDSPControl(),
   6108                                                     mkU32(0x00100000)),
   6109                                               getDSPControl()));
   6110                      /* Saturate if needed. */
   6111                      assign(t4, IRExpr_ITE(mkexpr(t1),
   6112                                            IRExpr_ITE(binop(Iop_CmpEQ32,
   6113                                                             mkexpr(t6),
   6114                                                             mkU32(0x0)),
   6115                                                       mkU16(0x7fff),
   6116                                                       mkU16(0x8000)),
   6117                                            unop(Iop_32to16, mkexpr(t0))));
   6118 
   6119                      /* Add higher halves. */
   6120                      assign(t2, binop(Iop_Add32,
   6121                                       unop(Iop_16Sto32,
   6122                                            unop(Iop_32HIto16, getIReg(rs))),
   6123                                       unop(Iop_16Sto32,
   6124                                            unop(Iop_32HIto16, getIReg(rt)))));
   6125 
   6126                      /* Bit 16 of the result. */
   6127                      assign(t7, binop(Iop_And32,
   6128                                       unop(Iop_16Uto32,
   6129                                            unop(Iop_32HIto16, mkexpr(t2))),
   6130                                       mkU32(0x1)));
   6131                      /* Detect overflow. */
   6132                      assign(t3, binop(Iop_CmpNE32,
   6133                                       binop(Iop_Shr32,
   6134                                             binop(Iop_And32,
   6135                                                   mkexpr(t2),
   6136                                                   mkU32(0x00008000)),
   6137                                             mkU8(15)),
   6138                                       mkexpr(t7)));
   6139 
   6140                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   6141                                               binop(Iop_Or32,
   6142                                                     getDSPControl(),
   6143                                                     mkU32(0x00100000)),
   6144                                               getDSPControl()));
   6145                      /* Saturate if needed. */
   6146                      assign(t5, IRExpr_ITE(mkexpr(t3),
   6147                                            IRExpr_ITE(binop(Iop_CmpEQ32,
   6148                                                             mkexpr(t7),
   6149                                                             mkU32(0x0)),
   6150                                                       mkU16(0x7fff),
   6151                                                       mkU16(0x8000)),
   6152                                            unop(Iop_32to16, mkexpr(t2))));
   6153 
   6154                      putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
   6155                      break;
   6156                   }
   6157                   case 0xF: {  /* SUBQ_S.PH */
   6158                      DIP("subq_s.ph r%d r%d, r%d", rd, rs, rt);
   6159                      vassert(!mode64);
   6160                      t0 = newTemp(Ity_I32);
   6161                      t1 = newTemp(Ity_I1);
   6162                      t2 = newTemp(Ity_I32);
   6163                      t3 = newTemp(Ity_I1);
   6164                      t4 = newTemp(Ity_I16);
   6165                      t5 = newTemp(Ity_I16);
   6166                      t6 = newTemp(Ity_I32);
   6167                      t7 = newTemp(Ity_I32);
   6168 
   6169                      /* Subtract lower halves. */
   6170                      assign(t0, binop(Iop_Sub32,
   6171                                       unop(Iop_16Sto32,
   6172                                            unop(Iop_32to16, getIReg(rs))),
   6173                                       unop(Iop_16Sto32,
   6174                                            unop(Iop_32to16, getIReg(rt)))));
   6175 
   6176                      /* Bit 16 of the result. */
   6177                      assign(t6, binop(Iop_And32,
   6178                                       unop(Iop_16Uto32,
   6179                                            unop(Iop_32HIto16, mkexpr(t0))),
   6180                                       mkU32(0x1)));
   6181                      /* Detect overflow or underflow. */
   6182                      assign(t1, binop(Iop_CmpNE32,
   6183                                       binop(Iop_Shr32,
   6184                                             binop(Iop_And32,
   6185                                                   mkexpr(t0),
   6186                                                   mkU32(0x8000)),
   6187                                             mkU8(15)),
   6188                                       mkexpr(t6)));
   6189 
   6190                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6191                                               binop(Iop_Or32,
   6192                                                     getDSPControl(),
   6193                                                     mkU32(0x00100000)),
   6194                                               getDSPControl()));
   6195                      /* Saturate if needed. */
   6196                      assign(t4, IRExpr_ITE(mkexpr(t1),
   6197                                            IRExpr_ITE(binop(Iop_CmpEQ32,
   6198                                                             mkexpr(t6),
   6199                                                             mkU32(0x0)),
   6200                                                       mkU16(0x7fff),
   6201                                                       mkU16(0x8000)),
   6202                                            unop(Iop_32to16, mkexpr(t0))));
   6203 
   6204                      /* Subtract higher halves. */
   6205                      assign(t2, binop(Iop_Sub32,
   6206                                       unop(Iop_16Sto32,
   6207                                            unop(Iop_32HIto16, getIReg(rs))),
   6208                                       unop(Iop_16Sto32,
   6209                                            unop(Iop_32HIto16, getIReg(rt)))));
   6210 
   6211                      /* Bit 16 of the result. */
   6212                      assign(t7, binop(Iop_And32,
   6213                                       unop(Iop_16Uto32,
   6214                                            unop(Iop_32HIto16, mkexpr(t2))),
   6215                                       mkU32(0x1)));
   6216                      /* Detect overflow or underflow. */
   6217                      assign(t3, binop(Iop_CmpNE32,
   6218                                       binop(Iop_Shr32,
   6219                                             binop(Iop_And32,
   6220                                                   mkexpr(t2),
   6221                                                   mkU32(0x00008000)),
   6222                                             mkU8(15)),
   6223                                       mkexpr(t7)));
   6224 
   6225                      putDSPControl(IRExpr_ITE(mkexpr(t3),
   6226                                               binop(Iop_Or32,
   6227                                                     getDSPControl(),
   6228                                                     mkU32(0x00100000)),
   6229                                               getDSPControl()));
   6230                      /* Saturate if needed. */
   6231                      assign(t5, IRExpr_ITE(mkexpr(t3),
   6232                                            IRExpr_ITE(binop(Iop_CmpEQ32,
   6233                                                             mkexpr(t7),
   6234                                                             mkU32(0x0)),
   6235                                                       mkU16(0x7fff),
   6236                                                       mkU16(0x8000)),
   6237                                            unop(Iop_32to16, mkexpr(t2))));
   6238 
   6239                      putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
   6240                      break;
   6241                   }
   6242                   case 0x10: {  /* ADDSC */
   6243                      DIP("addsc r%d, r%d, r%d", rd, rs, rt);
   6244                      vassert(!mode64);
   6245                      t0 = newTemp(Ity_I64);
   6246                      t1 = newTemp(Ity_I1);
   6247 
   6248                      /* The carry bit result out of the addition operation is
   6249                         written to bit 13(the c field) of the DSPControl reg. */
   6250                      assign(t0, binop(Iop_Add64,
   6251                                       unop(Iop_32Uto64, getIReg(rs)),
   6252                                       unop(Iop_32Uto64, getIReg(rt))));
   6253 
   6254                      assign(t1, binop(Iop_CmpEQ32,
   6255                                       binop(Iop_And32,
   6256                                             unop(Iop_64HIto32, mkexpr(t0)),
   6257                                             mkU32(0x1)),
   6258                                       mkU32(0x1)));
   6259                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6260                                               binop(Iop_Or32,
   6261                                                     getDSPControl(),
   6262                                                     mkU32(0x2000)),
   6263                                               binop(Iop_And32,
   6264                                                     getDSPControl(),
   6265                                                     mkU32(0xffffdfff))));
   6266 
   6267                      putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
   6268                      break;
   6269                   }
   6270                   case 0x11: {  /* ADDWC */
   6271                      DIP("addwc r%d, r%d, r%d", rd, rs, rt);
   6272                      vassert(!mode64);
   6273                      t0 = newTemp(Ity_I32);
   6274                      t1 = newTemp(Ity_I64);
   6275                      t2 = newTemp(Ity_I32);
   6276                      t3 = newTemp(Ity_I32);
   6277                      t4 = newTemp(Ity_I1);
   6278 
   6279                      /* Get carry bit from DSPControl register. */
   6280                      assign(t0, binop(Iop_Shr32,
   6281                                        binop(Iop_And32,
   6282                                              getDSPControl(),
   6283                                              mkU32(0x2000)),
   6284                                        mkU8(0xd)));
   6285                      assign(t1, binop(Iop_Add64,
   6286                                       unop(Iop_32Sto64, getIReg(rs)),
   6287                                       unop(Iop_32Sto64,
   6288                                            binop(Iop_Add32,
   6289                                                  getIReg(rt),
   6290                                                  mkexpr(t0)))));
   6291 
   6292                      /* Extract bits 32 and 31. */
   6293                      assign(t2, binop(Iop_And32,
   6294                                       unop(Iop_64HIto32, mkexpr(t1)),
   6295                                       mkU32(0x1)));
   6296                      assign(t3, binop(Iop_Shr32,
   6297                                       binop(Iop_And32,
   6298                                             unop(Iop_64to32, mkexpr(t1)),
   6299                                             mkU32(0x80000000)),
   6300                                       mkU8(31)));
   6301                      assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
   6302 
   6303                      putDSPControl(IRExpr_ITE(mkexpr(t4),
   6304                                               binop(Iop_Or32,
   6305                                                     getDSPControl(),
   6306                                                     mkU32(0x00100000)),
   6307                                               getDSPControl()));
   6308                      putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
   6309                      break;
   6310                   }
   6311                   case 0x12: {  /* MODSUB */
   6312                      DIP("modsub r%d, r%d, r%d", rd, rs, rt);
   6313                      vassert(!mode64);
   6314                      t0 = newTemp(Ity_I32);
   6315                      t1 = newTemp(Ity_I32);
   6316                      t2 = newTemp(Ity_I32);
   6317 
   6318                      /* decr_7..0 */
   6319                      assign(t0,
   6320                             unop(Iop_8Uto32,
   6321                                  unop(Iop_16to8,
   6322                                       unop(Iop_32to16, getIReg(rt)))));
   6323 
   6324                      /* lastindex_15..0 */
   6325                      assign(t1,
   6326                             unop(Iop_16Uto32,
   6327                                  binop(Iop_8HLto16,
   6328                                        unop(Iop_16to8,
   6329                                             unop(Iop_32HIto16, getIReg(rt))),
   6330                                        unop(Iop_16HIto8,
   6331                                             unop(Iop_32to16, getIReg(rt))))));
   6332                      /* temp_15..0 */
   6333                      assign(t2,
   6334                             IRExpr_ITE(binop(Iop_CmpEQ32,
   6335                                              getIReg(rs),
   6336                                              mkU32(0x00000000)),
   6337                                        mkexpr(t1),
   6338                                        binop(Iop_Sub32,
   6339                                              getIReg(rs), mkexpr(t0))));
   6340                      putIReg(rd, mkexpr(t2));
   6341                      break;
   6342                   }
   6343                   case 0x14: {  /* RADDU.W.QB */
   6344                      DIP("raddu.w.qb r%d, r%d", rd, rs);
   6345                      vassert(!mode64);
   6346                      putIReg(rd, binop(Iop_Add32,
   6347                                        binop(Iop_Add32,
   6348                                              unop(Iop_8Uto32,
   6349                                                   unop(Iop_16to8,
   6350                                                        unop(Iop_32to16,
   6351                                                             getIReg(rs)))),
   6352                                              unop(Iop_8Uto32,
   6353                                                   unop(Iop_16HIto8,
   6354                                                        unop(Iop_32to16,
   6355                                                             getIReg(rs))))),
   6356                                        binop(Iop_Add32,
   6357                                              unop(Iop_8Uto32,
   6358                                                   unop(Iop_16to8,
   6359                                                        unop(Iop_32HIto16,
   6360                                                             getIReg(rs)))),
   6361                                              unop(Iop_8Uto32,
   6362                                                   unop(Iop_16HIto8,
   6363                                                        unop(Iop_32HIto16,
   6364                                                             getIReg(rs)))))));
   6365                      break;
   6366                   }
   6367                   case 0x16: {  /* ADDQ_S.W */
   6368                      DIP("addq_s.w r%d, r%d, r%d", rd, rs, rt);
   6369                      vassert(!mode64);
   6370                      t0 = newTemp(Ity_I64);
   6371                      t1 = newTemp(Ity_I1);
   6372                      t2 = newTemp(Ity_I32);
   6373                      t3 = newTemp(Ity_I32);
   6374 
   6375                      assign(t0, binop(Iop_Add64,
   6376                                       unop(Iop_32Sto64, getIReg(rs)),
   6377                                       unop(Iop_32Sto64, getIReg(rt))));
   6378 
   6379                      assign(t3, binop(Iop_And32,
   6380                                       unop(Iop_64HIto32, mkexpr(t0)),
   6381                                       mkU32(0x1)));
   6382                      assign(t1, binop(Iop_CmpNE32,
   6383                                       binop(Iop_Shr32,
   6384                                             binop(Iop_And32,
   6385                                                   unop(Iop_64to32, mkexpr(t0)),
   6386                                                   mkU32(0x80000000)),
   6387                                             mkU8(31)),
   6388                                       mkexpr(t3)));
   6389 
   6390                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6391                                               binop(Iop_Or32,
   6392                                                     getDSPControl(),
   6393                                                     mkU32(0x00100000)),
   6394                                               getDSPControl()));
   6395 
   6396                      putIReg(rd, IRExpr_ITE(mkexpr(t1),
   6397                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   6398                                                              mkexpr(t3),
   6399                                                              mkU32(0x0)),
   6400                                                        mkU32(0x7fffffff),
   6401                                                        mkU32(0x80000000)),
   6402                                             unop(Iop_64to32, mkexpr(t0))));
   6403                      break;
   6404                   }
   6405                   case 0x17: {  /* SUBQ_S.W */
   6406                      DIP("subq_s.w r%d, r%d, r%d", rd, rs, rt);
   6407                      vassert(!mode64);
   6408                      t0 = newTemp(Ity_I64);
   6409                      t1 = newTemp(Ity_I1);
   6410                      t2 = newTemp(Ity_I32);
   6411                      t3 = newTemp(Ity_I32);
   6412 
   6413                      assign(t0, binop(Iop_Sub64,
   6414                                       unop(Iop_32Sto64, getIReg(rs)),
   6415                                       unop(Iop_32Sto64, getIReg(rt))));
   6416 
   6417                      assign(t3, binop(Iop_And32,
   6418                                       unop(Iop_64HIto32, mkexpr(t0)),
   6419                                       mkU32(0x1)));
   6420                      assign(t1, binop(Iop_CmpNE32,
   6421                                       binop(Iop_Shr32,
   6422                                             binop(Iop_And32,
   6423                                                   unop(Iop_64to32, mkexpr(t0)),
   6424                                                   mkU32(0x80000000)),
   6425                                             mkU8(31)),
   6426                                       mkexpr(t3)));
   6427 
   6428                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6429                                               binop(Iop_Or32,
   6430                                                     getDSPControl(),
   6431                                                     mkU32(0x00100000)),
   6432                                               getDSPControl()));
   6433 
   6434                      putIReg(rd, IRExpr_ITE(mkexpr(t1),
   6435                                             IRExpr_ITE(binop(Iop_CmpEQ32,
   6436                                                              mkexpr(t3),
   6437                                                              mkU32(0x0)),
   6438                                                        mkU32(0x7fffffff),
   6439                                                        mkU32(0x80000000)),
   6440                                             unop(Iop_64to32, mkexpr(t0))));
   6441                      break;
   6442                   }
   6443                   case 0x1C: {  /* MULEQ_S.W.PHL */
   6444                      DIP("muleq_s.w.phl r%d, r%d, r%d", rd, rs, rt);
   6445                      vassert(!mode64);
   6446                      t0 = newTemp(Ity_I32);
   6447                      t1 = newTemp(Ity_I1);
   6448                      t2 = newTemp(Ity_I1);
   6449                      t3 = newTemp(Ity_I32);
   6450 
   6451                      assign(t0,
   6452                             binop(Iop_Shl32,
   6453                                   binop(Iop_Mul32,
   6454                                         unop(Iop_16Sto32,
   6455                                              unop(Iop_32HIto16, getIReg(rt))),
   6456                                         unop(Iop_16Sto32,
   6457                                              unop(Iop_32HIto16, getIReg(rs)))),
   6458                                   mkU8(0x1)));
   6459                      assign(t1, binop(Iop_CmpEQ32,
   6460                                       binop(Iop_And32,
   6461                                             getIReg(rt),
   6462                                             mkU32(0xffff0000)),
   6463                                       mkU32(0x80000000)));
   6464                      assign(t2, binop(Iop_CmpEQ32,
   6465                                       binop(Iop_And32,
   6466                                             getIReg(rs),
   6467                                             mkU32(0xffff0000)),
   6468                                       mkU32(0x80000000)));
   6469                      assign(t3, IRExpr_ITE(mkexpr(t1),
   6470                                            IRExpr_ITE(mkexpr(t2),
   6471                                                       binop(Iop_Or32,
   6472                                                             getDSPControl(),
   6473                                                             mkU32(0x00200000)),
   6474                                                       getDSPControl()),
   6475                                            getDSPControl()));
   6476                      putDSPControl(mkexpr(t3));
   6477 
   6478                      putIReg(rd, IRExpr_ITE(mkexpr(t1),
   6479                                             IRExpr_ITE(mkexpr(t2),
   6480                                                        mkU32(0x7fffffff),
   6481                                                        mkexpr(t0)),
   6482                                             mkexpr(t0)));
   6483                      break;
   6484                   }
   6485                   case 0x1D: {  /* MULEQ_S.W.PHR */
   6486                      DIP("muleq_s.w.phr r%d, r%d, r%d", rd, rs, rt);
   6487                      vassert(!mode64);
   6488                      t0 = newTemp(Ity_I32);
   6489                      t1 = newTemp(Ity_I1);
   6490                      t2 = newTemp(Ity_I1);
   6491 
   6492                      assign(t0,
   6493                             binop(Iop_Shl32,
   6494                                   binop(Iop_Mul32,
   6495                                         unop(Iop_16Sto32,
   6496                                              unop(Iop_32to16, getIReg(rt))),
   6497                                         unop(Iop_16Sto32,
   6498                                              unop(Iop_32to16, getIReg(rs)))),
   6499                                   mkU8(0x1)));
   6500                      assign(t1, binop(Iop_CmpEQ32,
   6501                                       binop(Iop_And32,
   6502                                             getIReg(rt),
   6503                                             mkU32(0xffff)),
   6504                                       mkU32(0x8000)));
   6505                      assign(t2, binop(Iop_CmpEQ32,
   6506                                       binop(Iop_And32,
   6507                                             getIReg(rs),
   6508                                             mkU32(0xffff)),
   6509                                       mkU32(0x8000)));
   6510                      putDSPControl(IRExpr_ITE(mkexpr(t1),
   6511                                               IRExpr_ITE(mkexpr(t2),
   6512                                                          binop(Iop_Or32,
   6513                                                                getDSPControl(),
   6514                                                                mkU32(0x00200000)
   6515                                                               ),
   6516                                                          getDSPControl()),
   6517                                               getDSPControl()));
   6518                      putIReg(rd, IRExpr_ITE(mkexpr(t1),
   6519                                             IRExpr_ITE(mkexpr(t2),
   6520                                                        mkU32(0x7fffffff),
   6521                                                        mkexpr(t0)),
   6522                                             mkexpr(t0)));
   6523                      break;
   6524                   }
   6525                   case 0x1E: {  /* MULQ_S.PH */
   6526                      DIP("mulq_s.ph r%d, r%d, r%d", rd, rs, rt);
   6527                      vassert(!mode64);
   6528                      t0 = newTemp(Ity_I32);
   6529                      t1 = newTemp(Ity_I32);
   6530                      t2 = newTemp(Ity_I16);
   6531                      t3 = newTemp(Ity_I16);
   6532                      t5 = newTemp(Ity_I32);
   6533                      t6 = newTemp(Ity_I32);
   6534                      t7 = newTemp(Ity_I32);
   6535                      t8 = newTemp(Ity_I32);
   6536 
   6537                      assign(t5,
   6538                             unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
   6539                      assign(t6,
   6540                             unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
   6541 
   6542                      assign(t7,
   6543                             unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
   6544                      assign(t8,
   6545                             unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
   6546 
   6547                      assign(t0, binop(Iop_And32,
   6548                                       unop(Iop_1Sto32,
   6549                                            binop(Iop_CmpEQ32,
   6550                                                  binop(Iop_And32,
   6551                                                        mkexpr(t5),
   6552                                                        mkU32(0xffff)),
   6553                                                  mkU32(0x8000))),
   6554                                       unop(Iop_1Sto32,
   6555                                            binop(Iop_CmpEQ32,
   6556                                                  binop(Iop_And32,
   6557                                                        mkexpr(t6),
   6558                                                        mkU32(0xffff)),
   6559                                                  mkU32(0x8000)))));
   6560                      assign(t1, binop(Iop_And32,
   6561                                       unop(Iop_1Sto32,
   6562                                            binop(Iop_CmpEQ32,
   6563                                                  binop(Iop_And32,
   6564                                                        mkexpr(t7),
   6565                                                        mkU32(0xffff)),
   6566                                                  mkU32(0x8000))),
   6567                                       unop(Iop_1Sto32,
   6568                                            binop(Iop_CmpEQ32,
   6569                                                  binop(Iop_And32,
   6570                                                        mkexpr(t8),
   6571                                                        mkU32(0xffff)),
   6572                                                  mkU32(0x8000)))));
   6573 
   6574                      putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
   6575                                                     binop(Iop_Or32,
   6576                                                           mkexpr(t0),
   6577                                                           mkexpr(t1)),
   6578                                                     mkU32(0x0)),
   6579                                               getDSPControl(),
   6580                                               binop(Iop_Or32,
   6581                                                     getDSPControl(),
   6582                                                     mkU32(0x200000))));
   6583 
   6584                      assign(t2, unop(Iop_32HIto16,
   6585                                      binop(Iop_Shl32,
   6586                                            unop(Iop_64to32,
   6587                                                 binop(Iop_MullS32,
   6588                                                       mkexpr(t7),
   6589                                                       mkexpr(t8))),
   6590                                            mkU8(0x1))));
   6591                      assign(t3, unop(Iop_32HIto16,
   6592                                      binop(