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-2012 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 
     38 #include "main_util.h"
     39 #include "main_globals.h"
     40 #include "guest_generic_bb_to_IR.h"
     41 #include "guest_mips_defs.h"
     42 
     43 /*------------------------------------------------------------*/
     44 /*--- Globals                                              ---*/
     45 /*------------------------------------------------------------*/
     46 
     47 /* These are set at the start of the translation of a instruction, so
     48    that we don't have to pass them around endlessly.  CONST means does
     49    not change during translation of the instruction.
     50 */
     51 
     52 /* CONST: is the host bigendian?  This has to do with float vs double
     53    register accesses on VFP, but it's complex and not properly thought
     54    out. */
     55 static Bool host_is_bigendian;
     56 
     57 /* Pointer to the guest code area. */
     58 static UChar *guest_code;
     59 
     60 /* The guest address corresponding to guest_code[0]. */
     61 static Addr32 guest_PC_bbstart;
     62 
     63 /* CONST: The guest address for the instruction currently being
     64    translated. */
     65 static Addr32 guest_PC_curr_instr;
     66 
     67 /* MOD: The IRSB* into which we're generating code. */
     68 static IRSB *irsb;
     69 
     70 /* Is our guest binary 32 or 64bit?  Set at each call to
     71    disInstr_MIPS below. */
     72 static Bool mode64 = False;
     73 
     74 /*------------------------------------------------------------*/
     75 /*--- Debugging output                                     ---*/
     76 /*------------------------------------------------------------*/
     77 
     78 #define DIP(format, args...)           \
     79    if (vex_traceflags & VEX_TRACE_FE)  \
     80       vex_printf(format, ## args)
     81 
     82 /*------------------------------------------------------------*/
     83 /*--- Helper bits and pieces for deconstructing the        ---*/
     84 /*--- mips insn stream.                                    ---*/
     85 /*------------------------------------------------------------*/
     86 
     87 /* ---------------- Integer registers ---------------- */
     88 
     89 static UInt integerGuestRegOffset(UInt iregNo)
     90 {
     91    /* Do we care about endianness here?  We do if sub-parts of integer
     92       registers are accessed, but I don't think that ever happens on
     93       MIPS. */
     94    UInt ret;
     95    switch (iregNo) {
     96       case 0:
     97          ret = offsetof(VexGuestMIPS32State, guest_r0); break;
     98       case 1:
     99          ret = offsetof(VexGuestMIPS32State, guest_r1); break;
    100       case 2:
    101          ret = offsetof(VexGuestMIPS32State, guest_r2); break;
    102       case 3:
    103          ret = offsetof(VexGuestMIPS32State, guest_r3); break;
    104       case 4:
    105          ret = offsetof(VexGuestMIPS32State, guest_r4); break;
    106       case 5:
    107          ret = offsetof(VexGuestMIPS32State, guest_r5); break;
    108       case 6:
    109          ret = offsetof(VexGuestMIPS32State, guest_r6); break;
    110       case 7:
    111          ret = offsetof(VexGuestMIPS32State, guest_r7); break;
    112       case 8:
    113          ret = offsetof(VexGuestMIPS32State, guest_r8); break;
    114       case 9:
    115          ret = offsetof(VexGuestMIPS32State, guest_r9); break;
    116       case 10:
    117          ret = offsetof(VexGuestMIPS32State, guest_r10); break;
    118       case 11:
    119          ret = offsetof(VexGuestMIPS32State, guest_r11); break;
    120       case 12:
    121          ret = offsetof(VexGuestMIPS32State, guest_r12); break;
    122       case 13:
    123          ret = offsetof(VexGuestMIPS32State, guest_r13); break;
    124       case 14:
    125          ret = offsetof(VexGuestMIPS32State, guest_r14); break;
    126       case 15:
    127          ret = offsetof(VexGuestMIPS32State, guest_r15); break;
    128       case 16:
    129          ret = offsetof(VexGuestMIPS32State, guest_r16); break;
    130       case 17:
    131          ret = offsetof(VexGuestMIPS32State, guest_r17); break;
    132       case 18:
    133          ret = offsetof(VexGuestMIPS32State, guest_r18); break;
    134       case 19:
    135          ret = offsetof(VexGuestMIPS32State, guest_r19); break;
    136       case 20:
    137          ret = offsetof(VexGuestMIPS32State, guest_r20); break;
    138       case 21:
    139          ret = offsetof(VexGuestMIPS32State, guest_r21); break;
    140       case 22:
    141          ret = offsetof(VexGuestMIPS32State, guest_r22); break;
    142       case 23:
    143          ret = offsetof(VexGuestMIPS32State, guest_r23); break;
    144       case 24:
    145          ret = offsetof(VexGuestMIPS32State, guest_r24); break;
    146       case 25:
    147          ret = offsetof(VexGuestMIPS32State, guest_r25); break;
    148       case 26:
    149          ret = offsetof(VexGuestMIPS32State, guest_r26); break;
    150       case 27:
    151          ret = offsetof(VexGuestMIPS32State, guest_r27); break;
    152       case 28:
    153          ret = offsetof(VexGuestMIPS32State, guest_r28); break;
    154       case 29:
    155          ret = offsetof(VexGuestMIPS32State, guest_r29); break;
    156       case 30:
    157          ret = offsetof(VexGuestMIPS32State, guest_r30); break;
    158       case 31:
    159          ret = offsetof(VexGuestMIPS32State, guest_r31); break;
    160       default:
    161          vassert(0);
    162          break;
    163    }
    164    return ret;
    165 }
    166 
    167 #define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
    168 
    169 /* ---------------- Floating point registers ---------------- */
    170 
    171 static UInt floatGuestRegOffset(UInt fregNo)
    172 {
    173    vassert(fregNo < 32);
    174    UInt ret;
    175    switch (fregNo) {
    176       case 0:
    177          ret = offsetof(VexGuestMIPS32State, guest_f0); break;
    178       case 1:
    179          ret = offsetof(VexGuestMIPS32State, guest_f1); break;
    180       case 2:
    181          ret = offsetof(VexGuestMIPS32State, guest_f2); break;
    182       case 3:
    183          ret = offsetof(VexGuestMIPS32State, guest_f3); break;
    184       case 4:
    185          ret = offsetof(VexGuestMIPS32State, guest_f4); break;
    186       case 5:
    187          ret = offsetof(VexGuestMIPS32State, guest_f5); break;
    188       case 6:
    189          ret = offsetof(VexGuestMIPS32State, guest_f6); break;
    190       case 7:
    191          ret = offsetof(VexGuestMIPS32State, guest_f7); break;
    192       case 8:
    193          ret = offsetof(VexGuestMIPS32State, guest_f8); break;
    194       case 9:
    195          ret = offsetof(VexGuestMIPS32State, guest_f9); break;
    196       case 10:
    197          ret = offsetof(VexGuestMIPS32State, guest_f10); break;
    198       case 11:
    199          ret = offsetof(VexGuestMIPS32State, guest_f11); break;
    200       case 12:
    201          ret = offsetof(VexGuestMIPS32State, guest_f12); break;
    202       case 13:
    203          ret = offsetof(VexGuestMIPS32State, guest_f13); break;
    204       case 14:
    205          ret = offsetof(VexGuestMIPS32State, guest_f14); break;
    206       case 15:
    207          ret = offsetof(VexGuestMIPS32State, guest_f15); break;
    208       case 16:
    209          ret = offsetof(VexGuestMIPS32State, guest_f16); break;
    210       case 17:
    211          ret = offsetof(VexGuestMIPS32State, guest_f17); break;
    212       case 18:
    213          ret = offsetof(VexGuestMIPS32State, guest_f18); break;
    214       case 19:
    215          ret = offsetof(VexGuestMIPS32State, guest_f19); break;
    216       case 20:
    217          ret = offsetof(VexGuestMIPS32State, guest_f20); break;
    218       case 21:
    219          ret = offsetof(VexGuestMIPS32State, guest_f21); break;
    220       case 22:
    221          ret = offsetof(VexGuestMIPS32State, guest_f22); break;
    222       case 23:
    223          ret = offsetof(VexGuestMIPS32State, guest_f23); break;
    224       case 24:
    225          ret = offsetof(VexGuestMIPS32State, guest_f24); break;
    226       case 25:
    227          ret = offsetof(VexGuestMIPS32State, guest_f25); break;
    228       case 26:
    229          ret = offsetof(VexGuestMIPS32State, guest_f26); break;
    230       case 27:
    231          ret = offsetof(VexGuestMIPS32State, guest_f27); break;
    232       case 28:
    233          ret = offsetof(VexGuestMIPS32State, guest_f28); break;
    234       case 29:
    235          ret = offsetof(VexGuestMIPS32State, guest_f29); break;
    236       case 30:
    237          ret = offsetof(VexGuestMIPS32State, guest_f30); break;
    238       case 31:
    239          ret = offsetof(VexGuestMIPS32State, guest_f31); break;
    240       default:
    241          vassert(0);
    242          break;
    243    }
    244    return ret;
    245 }
    246 
    247 /* Do a endian load of a 32-bit word, regardless of the
    248    endianness of the underlying host. */
    249 static inline UInt getUInt(UChar * p)
    250 {
    251    UInt w = 0;
    252 #if defined (_MIPSEL)
    253    w = (w << 8) | p[3];
    254    w = (w << 8) | p[2];
    255    w = (w << 8) | p[1];
    256    w = (w << 8) | p[0];
    257 #elif defined (_MIPSEB)
    258    w = (w << 8) | p[0];
    259    w = (w << 8) | p[1];
    260    w = (w << 8) | p[2];
    261    w = (w << 8) | p[3];
    262 #endif
    263    return w;
    264 }
    265 
    266 #define BITS2(_b1,_b0) \
    267    (((_b1) << 1) | (_b0))
    268 
    269 #define BITS3(_b2,_b1,_b0)                      \
    270   (((_b2) << 2) | ((_b1) << 1) | (_b0))
    271 
    272 #define BITS4(_b3,_b2,_b1,_b0) \
    273    (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
    274 
    275 #define BITS5(_b4,_b3,_b2,_b1,_b0)  \
    276    (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
    277 
    278 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
    279    ((BITS2((_b5),(_b4)) << 4) \
    280     | BITS4((_b3),(_b2),(_b1),(_b0)))
    281 
    282 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
    283    ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
    284     | BITS4((_b3),(_b2),(_b1),(_b0)))
    285 
    286 #define LOAD_STORE_PATTERN \
    287     t1 = newTemp(Ity_I32); \
    288     assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); \
    289 
    290 #define LWX_SWX_PATTERN \
    291    t2 = newTemp(Ity_I32); \
    292    assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
    293    t4 = newTemp(Ity_I32); \
    294    assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
    295 
    296 #define SXXV_PATTERN(op) \
    297    putIReg(rd, binop(op, \
    298          getIReg(rt), \
    299             unop(Iop_32to8, \
    300                binop(Iop_And32, \
    301                   getIReg(rs), \
    302                   mkU32(0x0000001F) \
    303                ) \
    304             ) \
    305          ) \
    306       )
    307 
    308 #define SXX_PATTERN(op) \
    309    putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
    310 
    311 #define ALU_PATTERN(op) \
    312    putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
    313 
    314 #define ALUI_PATTERN(op) \
    315    putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
    316 
    317 #define ALUI_PATTERN64(op) \
    318    putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
    319 
    320 #define FP_CONDITIONAL_CODE \
    321     t3 = newTemp(Ity_I32);  \
    322     assign(t3, binop(Iop_And32, IRExpr_Mux0X( unop(Iop_1Uto8, \
    323                binop(Iop_CmpEQ32, mkU32(cc), mkU32(0))), \
    324                binop(Iop_Shr32, getFCSR(), mkU8(24+cc)),  \
    325                binop(Iop_Shr32, getFCSR(), mkU8(23))), mkU32(0x1)));
    326 
    327 /*------------------------------------------------------------*/
    328 /*---                           Field helpers              ---*/
    329 /*------------------------------------------------------------*/
    330 
    331 static UInt get_opcode(UInt mipsins)
    332 {
    333    return (0xFC000000 & mipsins) >> 26;
    334 }
    335 
    336 static UInt get_rs(UInt mipsins)
    337 {
    338    return (0x03E00000 & mipsins) >> 21;
    339 }
    340 
    341 static UInt get_rt(UInt mipsins)
    342 {
    343    return (0x001F0000 & mipsins) >> 16;
    344 }
    345 
    346 static UInt get_imm(UInt mipsins)
    347 {
    348    return (0x0000FFFF & mipsins);
    349 }
    350 
    351 static UInt get_instr_index(UInt mipsins)
    352 {
    353    return (0x03FFFFFF & mipsins);
    354 }
    355 
    356 static UInt get_rd(UInt mipsins)
    357 {
    358    return (0x0000F800 & mipsins) >> 11;
    359 }
    360 
    361 static UInt get_sa(UInt mipsins)
    362 {
    363    return (0x000007C0 & mipsins) >> 6;
    364 }
    365 
    366 static UInt get_function(UInt mipsins)
    367 {
    368    return (0x0000003F & mipsins);
    369 }
    370 
    371 static UInt get_ft(UInt mipsins)
    372 {
    373    return (0x001F0000 & mipsins) >> 16;
    374 }
    375 
    376 static UInt get_fs(UInt mipsins)
    377 {
    378    return (0x0000F800 & mipsins) >> 11;
    379 }
    380 
    381 static UInt get_fd(UInt mipsins)
    382 {
    383    return (0x000007C0 & mipsins) >> 6;
    384 }
    385 
    386 static UInt get_mov_cc(UInt mipsins)
    387 {
    388    return (0x001C0000 & mipsins) >> 18;
    389 }
    390 
    391 static UInt get_bc1_cc(UInt mipsins)
    392 {
    393    return (0x001C0000 & mipsins) >> 18;
    394 }
    395 
    396 static UInt get_fpc_cc(UInt mipsins)
    397 {
    398    return (0x00000700 & mipsins) >> 8;
    399 }
    400 
    401 static UInt get_tf(UInt mipsins)
    402 {
    403    return (0x00010000 & mipsins) >> 16;
    404 }
    405 
    406 static UInt get_nd(UInt mipsins)
    407 {
    408    return (0x00020000 & mipsins) >> 17;
    409 }
    410 
    411 static UInt get_fmt(UInt mipsins)
    412 {
    413    return (0x03E00000 & mipsins) >> 21;
    414 }
    415 
    416 static UInt get_FC(UInt mipsins)
    417 {
    418    return (0x000000F0 & mipsins) >> 4;
    419 }
    420 
    421 static UInt get_cond(UInt mipsins)
    422 {
    423    return (0x0000000F & mipsins);
    424 }
    425 
    426 /* for break & syscall */
    427 static UInt get_code(UInt mipsins)
    428 {
    429    return (0xFFC0 & mipsins) >> 6;
    430 }
    431 
    432 static UInt get_lsb(UInt mipsins)
    433 {
    434    return (0x7C0 & mipsins) >> 6;
    435 }
    436 
    437 static UInt get_msb(UInt mipsins)
    438 {
    439    return (0x0000F800 & mipsins) >> 11;
    440 }
    441 
    442 static UInt get_rot(UInt mipsins)
    443 {
    444    return (0x00200000 & mipsins) >> 21;
    445 }
    446 
    447 static UInt get_rotv(UInt mipsins)
    448 {
    449    return (0x00000040 & mipsins) >> 6;
    450 }
    451 
    452 static UInt get_sel(UInt mipsins)
    453 {
    454    return (0x00000007 & mipsins);
    455 }
    456 
    457 static Bool branch_or_jump(UChar * addr)
    458 {
    459    UInt fmt;
    460    UInt cins = getUInt(addr);
    461 
    462    UInt opcode = get_opcode(cins);
    463    UInt rt = get_rt(cins);
    464    UInt function = get_function(cins);
    465 
    466    /* bgtz, blez, bne, beq, jal */
    467    if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
    468        || opcode == 0x03 || opcode == 0x02) {
    469       return True;
    470    }
    471 
    472    /* bgez */
    473    if (opcode == 0x01 && rt == 0x01) {
    474       return True;
    475    }
    476 
    477    /* bgezal */
    478    if (opcode == 0x01 && rt == 0x11) {
    479       return True;
    480    }
    481 
    482    /* bltzal */
    483    if (opcode == 0x01 && rt == 0x10) {
    484       return True;
    485    }
    486 
    487    /* bltz */
    488    if (opcode == 0x01 && rt == 0x00) {
    489       return True;
    490    }
    491 
    492    /* jalr */
    493    if (opcode == 0x00 && function == 0x09) {
    494       return True;
    495    }
    496 
    497    /* jr */
    498    if (opcode == 0x00 && function == 0x08) {
    499       return True;
    500    }
    501 
    502    if (opcode == 0x11) {
    503       /*bc1f & bc1t */
    504       fmt = get_fmt(cins);
    505       if (fmt == 0x08) {
    506          return True;
    507       }
    508    }
    509 
    510    return False;
    511 }
    512 
    513 static Bool is_Branch_or_Jump_and_Link(UChar * addr)
    514 {
    515    UInt cins = getUInt(addr);
    516 
    517    UInt opcode = get_opcode(cins);
    518    UInt rt = get_rt(cins);
    519    UInt function = get_function(cins);
    520 
    521    /* jal */
    522    if (opcode == 0x02) {
    523       return True;
    524    }
    525 
    526    /* bgezal */
    527    if (opcode == 0x01 && rt == 0x11) {
    528       return True;
    529    }
    530 
    531    /* bltzal */
    532    if (opcode == 0x01 && rt == 0x10) {
    533       return True;
    534    }
    535 
    536    /* jalr */
    537    if (opcode == 0x00 && function == 0x09) {
    538       return True;
    539    }
    540 
    541    return False;
    542 }
    543 
    544 static Bool branch_or_link_likely(UChar * addr)
    545 {
    546    UInt cins = getUInt(addr);
    547    UInt opcode = get_opcode(cins);
    548    UInt rt = get_rt(cins);
    549 
    550    /* bgtzl, blezl, bnel, beql */
    551    if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
    552       return True;
    553 
    554    /* bgezl */
    555    if (opcode == 0x01 && rt == 0x03)
    556       return True;
    557 
    558    /* bgezall */
    559    if (opcode == 0x01 && rt == 0x13)
    560       return True;
    561 
    562    /* bltzall */
    563    if (opcode == 0x01 && rt == 0x12)
    564       return True;
    565 
    566    /* bltzl */
    567    if (opcode == 0x01 && rt == 0x02)
    568       return True;
    569 
    570    return False;
    571 }
    572 
    573 /*------------------------------------------------------------*/
    574 /*--- Helper bits and pieces for creating IR fragments.    ---*/
    575 /*------------------------------------------------------------*/
    576 
    577 static IRExpr *mkU8(UInt i)
    578 {
    579    vassert(i < 256);
    580    return IRExpr_Const(IRConst_U8((UChar) i));
    581 }
    582 
    583 /* Create an expression node for a 32-bit integer constant */
    584 static IRExpr *mkU32(UInt i)
    585 {
    586    return IRExpr_Const(IRConst_U32(i));
    587 }
    588 
    589 /* Create an expression node for a 64-bit integer constant */
    590 static IRExpr *mkU64(ULong i)
    591 {
    592    return IRExpr_Const(IRConst_U64(i));
    593 }
    594 
    595 static IRExpr *mkexpr(IRTemp tmp)
    596 {
    597    return IRExpr_RdTmp(tmp);
    598 }
    599 
    600 static IRExpr *unop(IROp op, IRExpr * a)
    601 {
    602    return IRExpr_Unop(op, a);
    603 }
    604 
    605 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
    606 {
    607    return IRExpr_Binop(op, a1, a2);
    608 }
    609 
    610 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
    611 {
    612    return IRExpr_Triop(op, a1, a2, a3);
    613 }
    614 
    615 static IRExpr *load(IRType ty, IRExpr * addr)
    616 {
    617    IRExpr *load1 = NULL;
    618 #if defined (_MIPSEL)
    619    load1 = IRExpr_Load(Iend_LE, ty, addr);
    620 #elif defined (_MIPSEB)
    621    load1 = IRExpr_Load(Iend_BE, ty, addr);
    622 #endif
    623    return load1;
    624 }
    625 
    626 /* Add a statement to the list held by "irsb". */
    627 static void stmt(IRStmt * st)
    628 {
    629    addStmtToIRSB(irsb, st);
    630 }
    631 
    632 static void assign(IRTemp dst, IRExpr * e)
    633 {
    634    stmt(IRStmt_WrTmp(dst, e));
    635 }
    636 
    637 static void store(IRExpr * addr, IRExpr * data)
    638 {
    639 #if defined (_MIPSEL)
    640    stmt(IRStmt_Store(Iend_LE, addr, data));
    641 #elif defined (_MIPSEB)
    642    stmt(IRStmt_Store(Iend_BE, addr, data));
    643 #endif
    644 }
    645 
    646 /* Generate a new temporary of the given type. */
    647 static IRTemp newTemp(IRType ty)
    648 {
    649    vassert(isPlausibleIRType(ty));
    650    return newIRTemp(irsb->tyenv, ty);
    651 }
    652 
    653 /* Generate an expression for SRC rotated right by ROT. */
    654 static IRExpr *genROR32(IRExpr * src, Int rot)
    655 {
    656    vassert(rot >= 0 && rot < 32);
    657    if (rot == 0)
    658       return src;
    659    return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
    660                           binop(Iop_Shr32, src, mkU8(rot)));
    661 }
    662 
    663 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
    664 {
    665    IRTemp t0 = newTemp(Ity_I8);
    666    IRTemp t1 = newTemp(Ity_I8);
    667 
    668    assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
    669    assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
    670    return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
    671                           binop(Iop_Shr32, src, mkexpr(t0)));
    672 }
    673 
    674 static UInt extend_s_16to32(UInt x)
    675 {
    676    return (UInt) ((((Int) x) << 16) >> 16);
    677 }
    678 
    679 static UInt extend_s_18to32(UInt x)
    680 {
    681    return (UInt) ((((Int) x) << 14) >> 14);
    682 }
    683 
    684 static void jmp_lit( /*MOD*/DisResult* dres,
    685                      IRJumpKind kind, Addr32 d32 )
    686 {
    687    vassert(dres->whatNext    == Dis_Continue);
    688    vassert(dres->len         == 0);
    689    vassert(dres->continueAt  == 0);
    690    vassert(dres->jk_StopHere == Ijk_INVALID);
    691    dres->whatNext    = Dis_StopHere;
    692    dres->jk_StopHere = kind;
    693    stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
    694 }
    695 
    696 /* Fetch a byte from the guest insn stream. */
    697 static UChar getIByte(Int delta)
    698 {
    699    return guest_code[delta];
    700 }
    701 
    702 static IRExpr *getIReg(UInt iregNo)
    703 {
    704    if (0 == iregNo) {
    705       return mode64 ? mkU64(0x0) : mkU32(0x0);
    706    } else {
    707       IRType ty = mode64 ? Ity_I64 : Ity_I32;
    708       vassert(iregNo < 32);
    709       return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
    710    }
    711 }
    712 
    713 static IRExpr *getHI(void)
    714 {
    715    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
    716 }
    717 
    718 static IRExpr *getLO(void)
    719 {
    720    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
    721 }
    722 
    723 static IRExpr *getFCSR(void)
    724 {
    725    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
    726 }
    727 
    728 static void putFCSR(IRExpr * e)
    729 {
    730    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
    731 }
    732 
    733 static IRExpr *getULR(void)
    734 {
    735    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
    736 }
    737 
    738 static void putIReg(UInt archreg, IRExpr * e)
    739 {
    740    IRType ty = mode64 ? Ity_I64 : Ity_I32;
    741    vassert(archreg < 32);
    742    vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
    743    if (archreg != 0)
    744       stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
    745 }
    746 
    747 static void putLO(IRExpr * e)
    748 {
    749    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
    750 }
    751 
    752 static void putHI(IRExpr * e)
    753 {
    754    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
    755 }
    756 
    757 static void putPC(IRExpr * e)
    758 {
    759    stmt(IRStmt_Put(OFFB_PC, e));
    760 }
    761 
    762 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
    763 {
    764    vassert(ty == Ity_I32 || ty == Ity_I64);
    765    if (ty == Ity_I32)
    766       return src;
    767    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
    768 }
    769 
    770 /* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
    771    of these combinations make sense. */
    772 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
    773 {
    774    IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
    775    if (src_ty == dst_ty)
    776       return e;
    777    if (src_ty == Ity_I32 && dst_ty == Ity_I16)
    778       return unop(Iop_32to16, e);
    779    if (src_ty == Ity_I32 && dst_ty == Ity_I8)
    780       return unop(Iop_32to8, e);
    781    if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
    782       vassert(mode64);
    783       return unop(Iop_64to8, e);
    784    }
    785    if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
    786       vassert(mode64);
    787       return unop(Iop_64to16, e);
    788    }
    789 
    790    if (vex_traceflags & VEX_TRACE_FE) {
    791       vex_printf("\nsrc, dst tys are: ");
    792       ppIRType(src_ty);
    793       vex_printf(", ");
    794       ppIRType(dst_ty);
    795       vex_printf("\n");
    796    }
    797 
    798    vpanic("narrowTo(mips)");
    799    return 0;
    800 }
    801 
    802 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
    803 {
    804    vassert(ty == Ity_I32 || ty == Ity_I64);
    805    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
    806 }
    807 
    808 static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
    809 {
    810    vassert(ty == Ity_F32 || ty == Ity_F64);
    811    if (ty == Ity_F64) {
    812       IRTemp t0, t1;
    813       t0 = newTemp(Ity_I64);
    814       t1 = newTemp(Ity_I32);
    815       assign(t0, unop(Iop_ReinterpF64asI64, src));
    816       assign(t1, unop(Iop_64to32, mkexpr(t0)));
    817       return unop(Iop_ReinterpI32asF32, mkexpr(t1));
    818    } else
    819       return src;
    820 }
    821 
    822 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
    823 {
    824    vassert(ty == Ity_F32 || ty == Ity_F64);
    825    return ty == Ity_F64 ? unop(Iop_F32toF64, src) : src;
    826 }
    827 
    828 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
    829 {
    830    ULong branch_offset;
    831    IRTemp t0;
    832 
    833    /* PC = PC + (SignExtend(signed_immed_24) << 2)
    834       An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
    835       is added to the address of the instruction following
    836       the branch (not the branch itself), in the branch delay slot, to form
    837       a PC-relative effective target address. */
    838    branch_offset = extend_s_18to32(imm << 2);
    839 
    840    t0 = newTemp(Ity_I1);
    841    assign(t0, guard);
    842 
    843    stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
    844                     IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
    845 
    846    irsb->jumpkind = Ijk_Boring;
    847 
    848    return mkU32(guest_PC_curr_instr + 4 + branch_offset);
    849 }
    850 
    851 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
    852 {
    853    ULong branch_offset;
    854    IRTemp t0;
    855 
    856    if (link) {    // LR (GPR31) = addr of the 2nd instr after branch instr
    857       putIReg(31, mkU32(guest_PC_curr_instr + 8));
    858    }
    859 
    860    /* PC = PC + (SignExtend(signed_immed_24) << 2)
    861       An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
    862       is added to the address of the instruction following
    863       the branch (not the branch itself), in the branch delay slot, to form
    864       a PC-relative effective target address. */
    865 
    866    branch_offset = extend_s_18to32(imm << 2);
    867 
    868    t0 = newTemp(Ity_I1);
    869    assign(t0, guard);
    870    *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
    871                    IRConst_U32(guest_PC_curr_instr + 4 + (UInt) branch_offset),
    872                    OFFB_PC);
    873 }
    874 
    875 static IRExpr *getFReg(UInt dregNo)
    876 {
    877    vassert(dregNo < 32);
    878    IRType ty = mode64 ? Ity_F64 : Ity_F32;
    879    return IRExpr_Get(floatGuestRegOffset(dregNo), ty);
    880 }
    881 
    882 static IRExpr *getDReg(UInt dregNo)
    883 {
    884    vassert(dregNo < 32);
    885    IRTemp t0 = newTemp(Ity_F32);
    886    IRTemp t1 = newTemp(Ity_F32);
    887    IRTemp t2 = newTemp(Ity_F64);
    888    IRTemp t3 = newTemp(Ity_I32);
    889    IRTemp t4 = newTemp(Ity_I32);
    890    IRTemp t5 = newTemp(Ity_I64);
    891 
    892    assign(t0, getFReg(dregNo));
    893    assign(t1, getFReg(dregNo + 1));
    894 
    895    assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
    896    assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
    897    assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
    898    assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
    899 
    900    return mkexpr(t2);
    901 }
    902 
    903 static void putFReg(UInt dregNo, IRExpr * e)
    904 {
    905    vassert(dregNo < 32);
    906    IRType ty = mode64 ? Ity_F64 : Ity_F32;
    907    vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
    908    stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
    909 }
    910 
    911 static void putDReg(UInt dregNo, IRExpr * e)
    912 {
    913    vassert(dregNo < 32);
    914    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
    915    IRTemp t1 = newTemp(Ity_F64);
    916    IRTemp t4 = newTemp(Ity_I32);
    917    IRTemp t5 = newTemp(Ity_I32);
    918    IRTemp t6 = newTemp(Ity_I64);
    919    assign(t1, e);
    920    assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
    921    assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  // hi
    922    assign(t5, unop(Iop_64to32, mkexpr(t6))); //lo
    923    putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
    924    putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
    925 }
    926 
    927 static void setFPUCondCode(IRExpr * e, UInt cc)
    928 {
    929    if (cc == 0) {
    930       DIP("setFpu: %d\n", cc);
    931       putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
    932       putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
    933    } else {
    934       DIP("setFpu1: %d\n", cc);
    935       putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
    936                                binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
    937       putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
    938    }
    939 }
    940 
    941 static IRExpr */* :: Ity_I32 */get_IR_roundingmode(void)
    942 {
    943 /*
    944    rounding mode | MIPS | IR
    945    ------------------------
    946    to nearest    | 00  | 00
    947    to zero       | 01  | 11
    948    to +infinity  | 10  | 10
    949    to -infinity  | 11  | 01
    950 */
    951    IRTemp rm_MIPS = newTemp(Ity_I32);
    952    /* Last two bits in FCSR are rounding mode. */
    953 
    954    assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
    955                                     guest_FCSR), Ity_I32), mkU32(3)));
    956 
    957    // rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2)
    958 
    959    return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
    960                 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
    961 }
    962 
    963 /*********************************************************/
    964 /*---             Floating Point Compare              ---*/
    965 /*********************************************************/
    966 static Bool dis_instr_CCondFmt(UInt cins)
    967 {
    968    IRTemp t0, t1, t2, t3;
    969    IRTemp ccIR = newTemp(Ity_I32);
    970    IRTemp ccMIPS = newTemp(Ity_I32);
    971    UInt FC = get_FC(cins);
    972    UInt fmt = get_fmt(cins);
    973    UInt fs = get_fs(cins);
    974    UInt ft = get_ft(cins);
    975    UInt cond = get_cond(cins);
    976 
    977    if (FC == 0x3) {  // C.cond.fmt
    978       UInt fpc_cc = get_fpc_cc(cins);
    979       switch (fmt) {
    980          case 0x10: {  //C.cond.S
    981             DIP("C.cond.S %d f%d, f%d\n", fpc_cc, fs, ft);
    982             t0 = newTemp(Ity_I32);
    983             t1 = newTemp(Ity_I32);
    984             t2 = newTemp(Ity_I32);
    985             t3 = newTemp(Ity_I32);
    986 
    987             assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
    988                                            unop(Iop_F32toF64, getFReg(ft))));
    989             /* Map compare result from IR to MIPS */
    990             /*
    991                FP cmp result | MIPS | IR
    992                --------------------------
    993                UN            | 0x1 | 0x45
    994                EQ            | 0x2 | 0x40
    995                GT            | 0x4 | 0x00
    996                LT            | 0x8 | 0x01
    997              */
    998 
    999             // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
   1000             //                    | ((ccIR ^ (ccIR>>6)) & 1)
   1001             assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
   1002                            binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
   1003                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
   1004                            binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
   1005                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
   1006                            mkU32(1))))));
   1007             assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
   1008             assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1009                    mkU8(0x1)), mkU32(0x1))); // EQ
   1010             assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
   1011                    mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
   1012             assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1013                    mkU8(0x3)), mkU32(0x1))); // LT
   1014 
   1015             switch (cond) {
   1016                case 0x0:
   1017                   setFPUCondCode(mkU32(0), fpc_cc);
   1018                   break;
   1019                case 0x1:
   1020                   DIP("unorderd: %d\n", fpc_cc);
   1021                   setFPUCondCode(mkexpr(t0), fpc_cc);
   1022                   break;
   1023                case 0x2:
   1024                   setFPUCondCode(mkexpr(t1), fpc_cc);
   1025                   break;
   1026                case 0x3:
   1027                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1028                                        fpc_cc);
   1029                   break;
   1030                case 0x4:
   1031                   setFPUCondCode(mkexpr(t3), fpc_cc);
   1032                   break;
   1033                case 0x5:
   1034                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1035                                        fpc_cc);
   1036                   break;
   1037                case 0x6:
   1038                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1039                                        fpc_cc);
   1040                   break;
   1041                case 0x7:
   1042                   setFPUCondCode(mkexpr(t2), fpc_cc);
   1043                   break;
   1044                case 0x8:
   1045                   setFPUCondCode(mkU32(0), fpc_cc);
   1046                   break;
   1047                case 0x9:
   1048                   setFPUCondCode(mkexpr(t0), fpc_cc);
   1049                   break;
   1050                case 0xA:
   1051                   setFPUCondCode(mkexpr(t1), fpc_cc);
   1052                   break;
   1053                case 0xB:
   1054                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1055                                        fpc_cc);
   1056                   break;
   1057                case 0xC:
   1058                   setFPUCondCode(mkexpr(t3), fpc_cc);
   1059                   break;
   1060                case 0xD:
   1061                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1062                                        fpc_cc);
   1063                   break;
   1064                case 0xE:
   1065                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1066                                        fpc_cc);
   1067                   break;
   1068                case 0xF:
   1069                   setFPUCondCode(mkexpr(t2), fpc_cc);
   1070                   break;
   1071 
   1072                default:
   1073                   return False;
   1074             }
   1075          }
   1076             break;
   1077 
   1078          case 0x11:  //C.cond.D
   1079             DIP("C.%d.D %d f%d, f%d\n", cond, fpc_cc, fs, ft);
   1080             t0 = newTemp(Ity_I32);
   1081             t1 = newTemp(Ity_I32);
   1082             t2 = newTemp(Ity_I32);
   1083             t3 = newTemp(Ity_I32);
   1084             assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
   1085             /* Map compare result from IR to MIPS */
   1086             /*
   1087                FP cmp result | MIPS | IR
   1088                --------------------------
   1089                UN            | 0x1 | 0x45
   1090                EQ            | 0x2 | 0x40
   1091                GT            | 0x4 | 0x00
   1092                LT            | 0x8 | 0x01
   1093              */
   1094 
   1095             // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
   1096             //                    | ((ccIR ^ (ccIR>>6)) & 1)
   1097             assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
   1098                            binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
   1099                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
   1100                            binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
   1101                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
   1102                            mkU32(1))))));
   1103 
   1104             assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
   1105             assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1106                    mkU8(0x1)), mkU32(0x1))); // EQ
   1107             assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
   1108                    mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
   1109             assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
   1110                    mkU8(0x3)), mkU32(0x1))); // LT
   1111 
   1112             switch (cond) {
   1113                case 0x0:
   1114                   setFPUCondCode(mkU32(0), fpc_cc);
   1115                   break;
   1116                case 0x1:
   1117                   DIP("unorderd: %d\n", fpc_cc);
   1118                   setFPUCondCode(mkexpr(t0), fpc_cc);
   1119                   break;
   1120                case 0x2:
   1121                   setFPUCondCode(mkexpr(t1), fpc_cc);
   1122                   break;
   1123                case 0x3:
   1124                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1125                                        fpc_cc);
   1126                   break;
   1127                case 0x4:
   1128                   setFPUCondCode(mkexpr(t3), fpc_cc);
   1129                   break;
   1130                case 0x5:
   1131                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1132                                        fpc_cc);
   1133                   break;
   1134                case 0x6:
   1135                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1136                                        fpc_cc);
   1137                   break;
   1138                case 0x7:
   1139                   setFPUCondCode(mkexpr(t2), fpc_cc);
   1140                   break;
   1141                case 0x8:
   1142                   setFPUCondCode(mkU32(0), fpc_cc);
   1143                   break;
   1144                case 0x9:
   1145                   setFPUCondCode(mkexpr(t0), fpc_cc);
   1146                   break;
   1147                case 0xA:
   1148                   setFPUCondCode(mkexpr(t1), fpc_cc);
   1149                   break;
   1150                case 0xB:
   1151                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
   1152                                        fpc_cc);
   1153                   break;
   1154                case 0xC:
   1155                   setFPUCondCode(mkexpr(t3), fpc_cc);
   1156                   break;
   1157                case 0xD:
   1158                   setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
   1159                                        fpc_cc);
   1160                   break;
   1161                case 0xE:
   1162                   setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
   1163                                        fpc_cc);
   1164                   break;
   1165                case 0xF:
   1166                   setFPUCondCode(mkexpr(t2), fpc_cc);
   1167                   break;
   1168                default:
   1169                   return False;
   1170             }
   1171             break;
   1172 
   1173             default:
   1174                return False;
   1175       }
   1176    } else {
   1177       return False;
   1178    }
   1179 
   1180    return True;
   1181 }
   1182 
   1183 /*------------------------------------------------------------*/
   1184 /*--- Disassemble a single instruction                     ---*/
   1185 /*------------------------------------------------------------*/
   1186 
   1187 /* Disassemble a single instruction into IR.  The instruction is
   1188    located in host memory at guest_instr, and has guest IP of
   1189    guest_PC_curr_instr, which will have been set before the call
   1190    here. */
   1191 
   1192 static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
   1193                                                                     Addr64),
   1194                                      Bool         resteerCisOk,
   1195                                      void*        callback_opaque,
   1196                                      Long         delta64,
   1197                                      VexArchInfo* archinfo,
   1198                                      VexAbiInfo*  abiinfo )
   1199 {
   1200    IRTemp t0, t1, t2, t3, t4, t5, t6, t7, t8;
   1201    UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
   1202         trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
   1203 
   1204    DisResult dres;
   1205 
   1206    static IRExpr *lastn = NULL;  /* last jump addr */
   1207    static IRStmt *bstmt = NULL;  /* branch (Exit) stmt */
   1208 
   1209    /* The running delta */
   1210    Int delta = (Int) delta64;
   1211 
   1212    /* Holds eip at the start of the insn, so that we can print
   1213       consistent error messages for unimplemented insns. */
   1214    Int delta_start = delta;
   1215 
   1216    /* Are we in a delay slot ? */
   1217    Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
   1218 
   1219    /* Set result defaults. */
   1220    dres.whatNext = Dis_Continue;
   1221    dres.len = 0;
   1222    dres.continueAt = 0;
   1223    dres.jk_StopHere = Ijk_INVALID;
   1224 
   1225    delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
   1226 
   1227    UChar *code = (UChar *) (guest_code + delta);
   1228    cins = getUInt(code);
   1229 
   1230    if (delta != 0) {
   1231       if (branch_or_jump(guest_code + delta - 4)) {
   1232          if (lastn == NULL && bstmt == NULL) {
   1233             DIP("Info: jump to delay slot insn...\n");
   1234          } else {
   1235             dres.whatNext = Dis_StopHere;
   1236 
   1237             DIP("lastn = %p bstmt = %p\n", lastn, bstmt);
   1238             if (lastn != NULL) {
   1239                DIP("delay slot jump\n");
   1240                if (vex_traceflags & VEX_TRACE_FE)
   1241                   ppIRExpr(lastn);
   1242                delay_slot_jump = True;
   1243             } else if (bstmt != NULL) {
   1244                DIP("\ndelay slot branch\n");
   1245                delay_slot_branch = True;
   1246             }
   1247             DIP("delay slot\n");
   1248          }
   1249       }
   1250 
   1251       if (branch_or_link_likely(guest_code + delta - 4)) {
   1252          likely_delay_slot = True;
   1253       }
   1254    }
   1255 
   1256    /* Spot "Special" instructions (see comment at top of file). */
   1257    {
   1258       /* Spot the 16-byte preamble:
   1259        ****mips32****
   1260        "srl $0, $0, 13
   1261        "srl $0, $0, 29
   1262        "srl $0, $0, 3
   1263        "srl $0, $0, 19 */
   1264       UInt word1 = 0x00000342;
   1265       UInt word2 = 0x00000742;
   1266       UInt word3 = 0x000000C2;
   1267       UInt word4 = 0x000004C2;
   1268       if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
   1269           getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
   1270          /* Got a "Special" instruction preamble.  Which one is it? */
   1271          if (getUInt(code + 16) == 0x01ad6825 /* or t5, t5, t5 */ ) {
   1272             /* v0 = client_request ( t9 ) */
   1273             DIP("v0 = client_request ( t9 )\n");
   1274             putPC(mkU32(guest_PC_curr_instr + 20));
   1275             dres.jk_StopHere = Ijk_ClientReq;
   1276             dres.whatNext    = Dis_StopHere;
   1277 
   1278             goto decode_success;
   1279          } else if (getUInt(code + 16) == 0x01ce7025 /* or t6,t6,t6 */ ) {
   1280             /* t9 = guest_NRADDR */
   1281             DIP("t9 = guest_NRADDR\n");
   1282             dres.len = 20;
   1283             delta += 20;
   1284             putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, guest_NRADDR),
   1285                                    Ity_I32));
   1286             goto decode_success;
   1287          } else if (getUInt(code + 16) == 0x01ef7825/* or t7,t7,t7 */ ) {
   1288             /*  branch-and-link-to-noredir t9 */
   1289             DIP("branch-and-link-to-noredir t9\n");
   1290             putIReg(31, mkU32(guest_PC_curr_instr + 20));
   1291             putPC(getIReg(25));
   1292             dres.jk_StopHere = Ijk_NoRedir;
   1293             dres.whatNext    = Dis_StopHere;
   1294             goto decode_success;
   1295          }
   1296 
   1297          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   1298             can print the insn following the Special-insn preamble. */
   1299          delta += 16;
   1300          goto decode_failure;
   1301        /*NOTREACHED*/}
   1302    }
   1303 
   1304    opcode = get_opcode(cins);
   1305    imm = get_imm(cins);
   1306    rs = get_rs(cins);
   1307    rt = get_rt(cins);
   1308    rd = get_rd(cins);
   1309    sa = get_sa(cins);
   1310    fs = get_fs(cins);
   1311    fd = get_fd(cins);
   1312    ft = get_ft(cins);
   1313    tf = get_tf(cins);
   1314    nd = get_nd(cins);
   1315    sel = get_sel(cins);
   1316    fmt = get_fmt(cins);
   1317    instr_index = get_instr_index(cins);
   1318    trap_code = get_code(cins);
   1319    function = get_function(cins);
   1320    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1321    IRType tyF = mode64 ? Ity_F64 : Ity_F32;
   1322 
   1323    DIP("[cins = 0x%08x] ", cins);
   1324 
   1325    switch (opcode) {
   1326 
   1327    case 0x03:     /* JAL */
   1328       DIP("jal 0x%x", instr_index);
   1329       putIReg(31, mkU32(guest_PC_curr_instr + 8));
   1330       t0 = newTemp(ty);
   1331       assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
   1332                        (instr_index << 2)));
   1333       lastn = mkexpr(t0);
   1334       break;
   1335    case 0x02:     /* J */
   1336       DIP("j 0x%x", instr_index);
   1337       t0 = newTemp(ty);
   1338       assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
   1339                        (instr_index << 2)));
   1340       lastn = mkexpr(t0);
   1341       break;
   1342 
   1343    case 0x11:     /* COP1 */
   1344       {
   1345          UInt bc1_cc = get_bc1_cc(cins);
   1346          if (0x08 == fmt) {
   1347             switch (fmt) {
   1348             case 0x08:  //BC
   1349                {
   1350                   DIP("tf: %d, nd: %d\n", tf, nd);
   1351                   //FcConditionalCode(bc1_cc)
   1352                   t1 = newTemp(Ity_I32);
   1353                   t2 = newTemp(Ity_I32);
   1354                   t3 = newTemp(Ity_I1);
   1355 
   1356                   assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1357                                                     mkU32(bc1_cc))));
   1358                   assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   1359                              binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1360                              mkU8(24 + bc1_cc)), mkU32(0x1)), binop(Iop_And32,
   1361                              binop(Iop_Shr32, getFCSR(), mkU8(23)),
   1362                                    mkU32(0x1))));
   1363 
   1364                   if (tf == 1 && nd == 0) {
   1365                      //branch on true
   1366                      DIP("bc1t %d, %d", bc1_cc, imm);
   1367                      assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
   1368                      dis_branch(False, mkexpr(t3), imm, &bstmt);
   1369                      break;
   1370                   } else if (tf == 0 && nd == 0) {
   1371                      //branch on false
   1372                      DIP("bc1f %d, %d", bc1_cc, imm);
   1373                      assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
   1374                      dis_branch(False, mkexpr(t3), imm, &bstmt);
   1375                      break;
   1376                   } else if (nd == 1 && tf == 0) {
   1377                      DIP("bc1fl %d, %d", bc1_cc, imm);
   1378                      lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
   1379                            mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
   1380                      break;
   1381                   } else if (nd == 1 && tf == 1) {
   1382                      DIP("bc1tl %d, %d", bc1_cc, imm);
   1383                      lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
   1384                                                mkU32(0x0)), imm);
   1385                      break;
   1386                   } else
   1387                      goto decode_failure;
   1388                }
   1389 
   1390             default:
   1391                goto decode_failure;
   1392             }
   1393          } else {
   1394             switch (function) {
   1395 
   1396             case 0x4:   //SQRT.fmt
   1397                {
   1398                   switch (fmt) {
   1399                   case 0x10:  //S
   1400                      {
   1401                         IRExpr *rm = get_IR_roundingmode();
   1402                         putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
   1403                                     getLoFromF64(tyF, getFReg(fs)))));
   1404                      }
   1405                      break;
   1406                   case 0x11:  //D
   1407                      {
   1408                         IRExpr *rm = get_IR_roundingmode();
   1409                         putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
   1410                      }
   1411                      break;
   1412                   }
   1413                }
   1414                break;
   1415             case 0x5:   //abs.fmt
   1416                switch (fmt) {
   1417                case 0x10:  //S
   1418                   DIP("abs.s f%d, f%d\n", fd, fs);
   1419                   putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
   1420                               getLoFromF64(tyF, getFReg(fs)))));
   1421                   break;
   1422                case 0x11:  //D
   1423                   DIP("abs.d f%d, f%d\n", fd, fs);
   1424                   putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
   1425                   break;
   1426                default:
   1427                   goto decode_failure;
   1428                }
   1429                break;   //case 0x5
   1430 
   1431             case 0x02:  // MUL.fmt
   1432                switch (fmt) {
   1433                case 0x11:  // D
   1434                   {
   1435                      DIP("mul.d f%d, f%d, f%d", fd, fs, ft);
   1436                      IRExpr *rm = get_IR_roundingmode();
   1437                      putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
   1438                                        getDReg(ft)));
   1439                      break;
   1440                   }
   1441                case 0x10:  // S
   1442                   {
   1443                      DIP("mul.s f%d, f%d, f%d", fd, fs, ft);
   1444                      IRExpr *rm = get_IR_roundingmode();
   1445                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
   1446                                  getLoFromF64(tyF, getFReg(fs)),
   1447                                  getLoFromF64(tyF, getFReg(ft)))));
   1448                      break;
   1449                   }
   1450                default:
   1451                   goto decode_failure;
   1452                }
   1453                break;   // MUL.fmt
   1454 
   1455             case 0x03:  // DIV.fmt
   1456                switch (fmt) {
   1457                case 0x11:  // D
   1458                   {
   1459                      DIP("div.d f%d, f%d, f%d", fd, fs, ft);
   1460                      IRExpr *rm = get_IR_roundingmode();
   1461                      putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
   1462                                  getDReg(ft)));
   1463                      break;
   1464                   }
   1465                case 0x10:  // S
   1466                   {
   1467                      DIP("div.s f%d, f%d, f%d", fd, fs, ft);
   1468                      IRExpr *rm = get_IR_roundingmode();
   1469                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
   1470                                  getLoFromF64(tyF, getFReg(fs)),
   1471                                  getLoFromF64(tyF, getFReg(ft)))));
   1472                      break;
   1473                   }
   1474                default:
   1475                   goto decode_failure;
   1476                }
   1477                break;   // DIV.fmt
   1478 
   1479             case 0x01:  // SUB.fmt
   1480                switch (fmt) {
   1481                case 0x11:  // D
   1482                   {
   1483                      DIP("sub.d f%d, f%d, f%d", fd, fs, ft);
   1484                      IRExpr *rm = get_IR_roundingmode();
   1485                      putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), getDReg(ft)));
   1486                      break;
   1487                   }
   1488                case 0x10:  // S
   1489                   {
   1490                      DIP("sub.s f%d, f%d, f%d", fd, fs, ft);
   1491                      IRExpr *rm = get_IR_roundingmode();
   1492                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
   1493                                  getLoFromF64(tyF, getFReg(fs)),
   1494                                  getLoFromF64(tyF, getFReg(ft)))));
   1495                      break;
   1496                   }
   1497                default:
   1498                   goto decode_failure;
   1499                }
   1500                break;   // SUB.fmt
   1501 
   1502             case 0x06:  // MOV.fmt
   1503                switch (fmt) {
   1504                case 0x11:  // D
   1505                   /* TODO: Check this for 64 bit FPU registers. */
   1506                   DIP("mov.d f%d, f%d", fd, fs);
   1507                   putFReg(fd, getFReg(fs));
   1508                   putFReg(fd + 1, getFReg(fs + 1));
   1509                   break;
   1510                case 0x10:  // S
   1511                   DIP("mov.s f%d, f%d", fd, fs);
   1512                   putFReg(fd, getFReg(fs));
   1513                   break;
   1514                default:
   1515                   goto decode_failure;
   1516                }
   1517                break;   // MOV.fmt
   1518 
   1519             case 0x7:   //neg.fmt
   1520                switch (fmt) {
   1521                case 0x10:  //S
   1522                   DIP("neg.s f%d, f%d", fd, fs);
   1523                   putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
   1524                               getLoFromF64(tyF, getFReg(fs)))));
   1525                   break;
   1526                case 0x11:  //D
   1527                   DIP("neg.d f%d, f%d", fd, fs);
   1528                   putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
   1529                   break;
   1530                default:
   1531                   goto decode_failure;
   1532                }
   1533                break;   //case 0x7
   1534 
   1535             case 0x15:  //RECIP.fmt
   1536                switch (fmt) {
   1537                case 0x10:
   1538                   {  //S
   1539                      DIP("recip.s f%d, f%d\n", fd, fs);
   1540                      IRExpr *rm = get_IR_roundingmode();
   1541                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
   1542                                  rm, unop(Iop_ReinterpI32asF32,
   1543                                  mkU32(0x3F800000)), getLoFromF64(tyF,
   1544                                  getFReg(fs)))));
   1545                      break;
   1546                   }
   1547                case 0x11:
   1548                   {  //D
   1549                      DIP("recip.d f%d, f%d\n", fd, fs);
   1550                      IRExpr *rm = get_IR_roundingmode();
   1551                      putDReg(fd, triop(Iop_DivF64, rm,
   1552                                  unop(Iop_ReinterpI64asF64,
   1553                                  mkU64(0x3FF0000000000000ULL)), getDReg(fs)));
   1554                      break;
   1555                   }
   1556                default:
   1557                   goto decode_failure;
   1558 
   1559                }
   1560                break;   //case 0x15
   1561 
   1562             case 0x13:  //MOVN.fmt
   1563                switch (fmt) {
   1564                case 0x10:  // S
   1565                   DIP("movn.s f%d, f%d, r%d", fd, fs, rt);
   1566 
   1567                   t1 = newTemp(Ity_F64);
   1568                   t2 = newTemp(Ity_F64);
   1569                   t3 = newTemp(Ity_I32);
   1570                   t4 = newTemp(Ity_F64);
   1571 
   1572                   assign(t1, unop(Iop_F32toF64, getFReg(fs)));
   1573                   assign(t2, unop(Iop_F32toF64, getFReg(fd)));
   1574                   assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
   1575                                                     getIReg(rt))));
   1576 
   1577                   assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1578                                                mkexpr(t2), mkexpr(t1)));
   1579 
   1580                   putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
   1581                                     mkexpr(t4)));
   1582                   break;
   1583                case 0x11:  // D
   1584                   DIP("movn.d f%d, f%d, r%d", fd, fs, rt);
   1585 
   1586                   t3 = newTemp(Ity_I32);
   1587                   t4 = newTemp(Ity_F64);
   1588 
   1589                   assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
   1590                                                     getIReg(rt))));
   1591                   putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1592                                                 getDReg(fd), getDReg(fs)));
   1593                   break;
   1594                default:
   1595                   goto decode_failure;
   1596                }
   1597                break;   // MOVN.fmt
   1598 
   1599             case 0x12:  //MOVZ.fmt
   1600                switch (fmt) {
   1601                case 0x10:  // S
   1602                   DIP("movz.s f%d, f%d, r%d", fd, fs, rt);
   1603 
   1604                   t1 = newTemp(Ity_F64);
   1605                   t2 = newTemp(Ity_F64);
   1606                   t3 = newTemp(Ity_I32);
   1607                   t4 = newTemp(Ity_F64);
   1608 
   1609                   assign(t1, unop(Iop_F32toF64, getFReg(fs)));
   1610                   assign(t2, unop(Iop_F32toF64, getFReg(fd)));
   1611                   assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1612                                                     getIReg(rt))));
   1613                   assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1614                                                mkexpr(t2), mkexpr(t1)));
   1615 
   1616                   putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
   1617                                     mkexpr(t4)));
   1618 
   1619                   break;
   1620                case 0x11:  // D
   1621                   DIP("movz.d f%d, f%d, r%d", fd, fs, rt);
   1622 
   1623                   t3 = newTemp(Ity_I32);
   1624                   t4 = newTemp(Ity_F64);
   1625 
   1626                   assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1627                                                     getIReg(rt))));
   1628                   putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1629                                                 getDReg(fd), getDReg(fs)));
   1630                   break;
   1631                default:
   1632                   goto decode_failure;
   1633                }
   1634                break;   // MOVZ.fmt
   1635 
   1636             case 0x11:  // MOVT.fmt
   1637                if (tf == 1) {
   1638                   UInt mov_cc = get_mov_cc(cins);
   1639                   switch (fmt)   // MOVCF = 010001
   1640                   {
   1641                   case 0x11:  // D
   1642                      DIP("movt.d f%d, f%d, %d", fd, fs, mov_cc);
   1643                      t1 = newTemp(Ity_I32);
   1644                      t2 = newTemp(Ity_I32);
   1645                      t3 = newTemp(Ity_I32);
   1646                      t4 = newTemp(Ity_F64);
   1647 
   1648                      assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1649                                                        mkU32(mov_cc))));
   1650                      assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   1651                                 binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1652                                  mkU8(24 + mov_cc)), mkU32(0x1)),
   1653                                  binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1654                                  mkU8(23)), mkU32(0x1))));
   1655 
   1656                      assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
   1657                                 mkexpr(t2))));
   1658                      assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1659                                              getDReg(fs), getDReg(fd)));
   1660                      putDReg(fd, mkexpr(t4));
   1661                      break;
   1662                   case 0x10:  // S
   1663                      DIP("movt.s f%d, f%d, %d", fd, fs, mov_cc);
   1664                      t1 = newTemp(Ity_I32);
   1665                      t2 = newTemp(Ity_I32);
   1666                      t3 = newTemp(Ity_I32);
   1667                      t4 = newTemp(Ity_F64);
   1668                      t5 = newTemp(Ity_F64);
   1669                      t6 = newTemp(Ity_F64);
   1670                      t7 = newTemp(Ity_I64);
   1671 
   1672                      assign(t5, unop(Iop_F32toF64, getFReg(fs)));
   1673                      assign(t6, unop(Iop_F32toF64, getFReg(fd)));
   1674 
   1675                      assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1676                                      mkU32(mov_cc))));
   1677                      assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   1678                                              binop(Iop_And32, binop(Iop_Shr32,
   1679                                              getFCSR(), mkU8(24 + mov_cc)),
   1680                                              mkU32(0x1)), binop(Iop_And32,
   1681                                              binop(Iop_Shr32, getFCSR(),
   1682                                              mkU8(23)), mkU32(0x1))));
   1683 
   1684                      assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
   1685                                                        mkexpr(t2))));
   1686                      assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1687                                              mkexpr(t5), mkexpr(t6)));
   1688 
   1689                      putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
   1690                                        mkexpr(t4)));
   1691                      break;
   1692                   default:
   1693                      goto decode_failure;
   1694                   }
   1695                } else if (tf == 0)  //movf.fmt
   1696                {
   1697                   UInt mov_cc = get_mov_cc(cins);
   1698                   switch (fmt)   // MOVCF = 010001
   1699                   {
   1700                   case 0x11:  // D
   1701                      DIP("movf.d f%d, f%d, %d", fd, fs, mov_cc);
   1702                      t1 = newTemp(Ity_I32);
   1703                      t2 = newTemp(Ity_I32);
   1704                      t3 = newTemp(Ity_I32);
   1705                      t4 = newTemp(Ity_F64);
   1706 
   1707                      assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32,
   1708                                                  mkU32(0), mkU32(mov_cc))));
   1709                      assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   1710                                 binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1711                                 mkU8(24 + mov_cc)), mkU32(0x1)),
   1712                                 binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1713                                 mkU8(23)), mkU32(0x1))));
   1714 
   1715                      assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
   1716                                                        mkexpr(t2))));
   1717                      assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1718                                              getDReg(fd), getDReg(fs)));
   1719                      putDReg(fd, mkexpr(t4));
   1720                      break;
   1721                   case 0x10:  // S
   1722                      DIP("movf.s f%d, f%d, %d", fd, fs, mov_cc);
   1723                      {
   1724                         t1 = newTemp(Ity_I32);
   1725                         t2 = newTemp(Ity_I32);
   1726                         t3 = newTemp(Ity_I32);
   1727                         t4 = newTemp(Ity_F64);
   1728                         t5 = newTemp(Ity_F64);
   1729                         t6 = newTemp(Ity_F64);
   1730 
   1731                         assign(t5, unop(Iop_F32toF64, getFReg(fs)));
   1732                         assign(t6, unop(Iop_F32toF64, getFReg(fd)));
   1733 
   1734                         assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   1735                                                           mkU32(mov_cc))));
   1736                         assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   1737                                    binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1738                                    mkU8(24 + mov_cc)), mkU32(0x1)),
   1739                                    binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   1740                                    mkU8(23)), mkU32(0x1))));
   1741 
   1742                         assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
   1743                                                           mkexpr(t2))));
   1744                         assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   1745                                                      mkexpr(t6), mkexpr(t5)));
   1746                         putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
   1747                                           mkexpr(t4)));
   1748                      }
   1749                      break;
   1750                   default:
   1751                      goto decode_failure;
   1752                   }
   1753                }
   1754 
   1755                break;   // MOVT.fmt
   1756 
   1757             case 0x0:   //add.fmt
   1758                switch (fmt) {
   1759                case 0x10:  //S
   1760                   {
   1761                      DIP("add.s f%d, f%d, f%d\n", fd, fs, ft);
   1762                      IRExpr *rm = get_IR_roundingmode();
   1763                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
   1764                                  getLoFromF64(tyF, getFReg(fs)),
   1765                                  getLoFromF64(tyF, getFReg(ft)))));
   1766                      break;
   1767                   }
   1768                case 0x11:  //D
   1769                   {
   1770                      DIP("add.d f%d, f%d, f%d\n", fd, fs, ft);
   1771                      IRExpr *rm = get_IR_roundingmode();
   1772                      putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs),
   1773                                        getDReg(ft)));
   1774                      break;
   1775                   }
   1776 
   1777                case 0x4:   //MTC1 (Move Word to Floating Point)
   1778                   DIP("mtc1 r%d, f%d", rt, fs);
   1779                   putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt)));
   1780                   break;
   1781 
   1782                case 0x0:   //MFC1
   1783                   DIP("mfc1 r%d, f%d", rt, fs);
   1784                   putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs)));
   1785                   break;
   1786 
   1787                case 0x6:   //CTC1
   1788                   DIP("ctc1 r%d, f%d", rt, fs);
   1789                   t0 = newTemp(Ity_I32);
   1790                   t1 = newTemp(Ity_I32);
   1791                   t2 = newTemp(Ity_I32);
   1792                   t3 = newTemp(Ity_I32);
   1793                   t4 = newTemp(Ity_I32);
   1794                   t5 = newTemp(Ity_I32);
   1795                   t6 = newTemp(Ity_I32);
   1796                   assign(t0, mkNarrowTo32(ty, getIReg(rt)));
   1797                   if (fs == 25) {   //FCCR
   1798                      assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
   1799                                       mkU32(0x000000FE)), mkU8(24)));
   1800                      assign(t2, binop(Iop_And32, mkexpr(t0),
   1801                                       mkU32(0x01000000)));
   1802                      assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
   1803                                       mkU32(0x00000001)), mkU8(23)));
   1804                      assign(t4, binop(Iop_And32, mkexpr(t0),
   1805                                       mkU32(0x007FFFFF)));
   1806                      putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
   1807                                    mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
   1808                                    mkexpr(t4))));
   1809                   } else if (fs == 26) {  //FEXR
   1810                      assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
   1811                      assign(t2, binop(Iop_And32, mkexpr(t0),
   1812                                       mkU32(0x0003F000)));
   1813                      assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
   1814                      assign(t4, binop(Iop_And32, mkexpr(t0),
   1815                                       mkU32(0x0000007C)));
   1816                      assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
   1817                      putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
   1818                                    mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
   1819                                    mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
   1820                   } else if (fs == 28) {
   1821                      assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
   1822                      assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
   1823                                 mkU32(0x00000002)), mkU8(22)));
   1824                      assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
   1825                      assign(t4, binop(Iop_And32, mkexpr(t0),
   1826                                 mkU32(0x00000F80)));
   1827                      assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
   1828                      assign(t6, binop(Iop_And32, mkexpr(t0),
   1829                                 mkU32(0x00000003)));
   1830                      putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
   1831                                    mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
   1832                                    mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
   1833                                    mkexpr(t5), mkexpr(t6))));
   1834                   } else if (fs == 31) {
   1835                      putFCSR(mkexpr(t0));
   1836                   }
   1837                   break;
   1838                case 0x2:   //CFC1
   1839                   DIP("cfc1 r%d, f%d", rt, fs);
   1840                   t0 = newTemp(Ity_I32);
   1841                   t1 = newTemp(Ity_I32);
   1842                   t2 = newTemp(Ity_I32);
   1843                   t3 = newTemp(Ity_I32);
   1844                   t4 = newTemp(Ity_I32);
   1845                   t5 = newTemp(Ity_I32);
   1846                   t6 = newTemp(Ity_I32);
   1847                   assign(t0, getFCSR());
   1848                   if (fs == 0) {
   1849                      putIReg(rt, mkWidenFrom32(ty,
   1850                              IRExpr_Get(offsetof(VexGuestMIPS32State,
   1851                                                  guest_FIR),
   1852                                        Ity_I32),
   1853                              False));
   1854                   } else if (fs == 25) {
   1855                      assign(t1, mkU32(0x000000FF));
   1856                      assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
   1857                                       mkU32(0xFE000000)), mkU8(25)));
   1858                      assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
   1859                                       mkU32(0x00800000)), mkU8(23)));
   1860                      putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
   1861                                  binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
   1862                                  mkexpr(t3)), False));
   1863                   } else if (fs == 26) {
   1864                      assign(t1, mkU32(0xFFFFF07C));
   1865                      assign(t2, binop(Iop_And32, mkexpr(t0),
   1866                                 mkU32(0x0003F000)));
   1867                      assign(t3, binop(Iop_And32, mkexpr(t0),
   1868                                       mkU32(0x0000007C)));
   1869                      putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
   1870                                  binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
   1871                                  mkexpr(t3)), False));
   1872                   } else if (fs == 28) {
   1873                      assign(t1, mkU32(0x00000F87));
   1874                      assign(t2, binop(Iop_And32, mkexpr(t0),
   1875                                       mkU32(0x00000F83)));
   1876                      assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
   1877                                       mkU32(0x01000000)), mkU8(22)));
   1878                      putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
   1879                                  binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
   1880                                  mkexpr(t3)), False));
   1881                   } else if (fs == 31) {
   1882                      putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
   1883                   }
   1884                   break;
   1885                default:
   1886                   goto decode_failure;
   1887                }
   1888                break;   //case 0x0: //add.fmt
   1889 
   1890             case 0x21:  //CVT.D
   1891                switch (fmt) {
   1892                case 0x10:  //S
   1893                   DIP("cvt.d.s f%d, f%d", fd, fs);
   1894                   putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
   1895                   break;
   1896 
   1897                case 0x14:
   1898                   {  //W
   1899                      DIP("cvt.d.w %d, %d\n", fd, fs);
   1900                      t0 = newTemp(Ity_I32);
   1901                      assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
   1902                      putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
   1903                   }
   1904                   break;
   1905 
   1906                default:
   1907                   goto decode_failure;
   1908                }
   1909                break;   //CVT.D
   1910 
   1911             case 0x20:  //cvt.s
   1912                switch (fmt) {
   1913                case 0x14:  //W
   1914                   DIP("cvt.s.w %d, %d\n", fd, fs);
   1915                   t0 = newTemp(Ity_I32);
   1916                   assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
   1917                   putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
   1918                               mkexpr(t0)));
   1919                   break;
   1920 
   1921                case 0x11:  //D
   1922                   DIP("cvt.s.d %d, %d\n", fd, fs);
   1923                   putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
   1924                                     getDReg(fs)));
   1925                   break;
   1926 
   1927                default:
   1928                   goto decode_failure;
   1929                }
   1930                break;   //cvt.s
   1931 
   1932             case 0x24:  //cvt.w
   1933                switch (fmt) {
   1934                case 0x10:  //S
   1935                   DIP("cvt.w.s %d, %d\n", fd, fs);
   1936                   putFReg(fd, binop(Iop_RoundF32toInt, get_IR_roundingmode(),
   1937                                     getFReg(fs)));
   1938                   break;
   1939 
   1940                case 0x11:
   1941                   {  //D
   1942                      DIP("cvt.w.d %d, %d\n", fd, fs);
   1943                      t0 = newTemp(Ity_I32);
   1944 
   1945                      assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
   1946                                       getDReg(fs)));
   1947 
   1948                      putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
   1949                   }
   1950                   break;
   1951 
   1952                default:
   1953                   goto decode_failure;
   1954 
   1955                }
   1956                break;
   1957 
   1958             case 0x09:  //TRUNC.L
   1959                switch (fmt) {
   1960                case 0x10:  //S
   1961                   DIP("trunc.l.s %d, %d\n", fd, fs);
   1962                   goto decode_failure;
   1963 
   1964                case 0x11:  //D
   1965                   DIP("trunc.l.d %d, %d\n", fd, fs);
   1966                   goto decode_failure;
   1967 
   1968                default:
   1969                   goto decode_failure;
   1970 
   1971                }
   1972                break;   //trunc.l
   1973 
   1974             case 0x0C:  //ROUND.W.fmt
   1975                switch (fmt) {
   1976                case 0x10:  //S
   1977                   DIP("round.w.s f%d, f%d\n", fd, fs);
   1978                   putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0),
   1979                                     getFReg(fs)));
   1980                   break;
   1981 
   1982                case 0x11:  //D
   1983                   DIP("round.w.d f%d, f%d\n", fd, fs);
   1984                   t0 = newTemp(Ity_I32);
   1985 
   1986                   assign(t0, binop(Iop_F64toI32S, mkU32(0x0), getDReg(fs)));
   1987 
   1988                   putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
   1989                   break;
   1990 
   1991                default:
   1992                   goto decode_failure;
   1993 
   1994                }
   1995                break;   //ROUND.W.fmt
   1996 
   1997             case 0x0F:  //FLOOR.W.fmt
   1998                switch (fmt) {
   1999                case 0x10:  //S
   2000                   DIP("floor.w.s f%d, f%d\n", fd, fs);
   2001                   putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1),
   2002                                     getFReg(fs)));
   2003                   break;
   2004 
   2005                case 0x11:  //D
   2006                   DIP("floor.w.d f%d, f%d\n", fd, fs);
   2007                   t0 = newTemp(Ity_I32);
   2008 
   2009                   assign(t0, binop(Iop_F64toI32S, mkU32(0x1), getDReg(fs)));
   2010 
   2011                   putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
   2012                   break;
   2013 
   2014                default:
   2015                   goto decode_failure;
   2016 
   2017                }
   2018                break;   //FLOOR.W.fmt
   2019 
   2020             case 0x0D:  //TRUNC.W
   2021                switch (fmt) {
   2022                case 0x10:  //S
   2023                   DIP("trunc.w.s %d, %d\n", fd, fs);
   2024                   putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3),
   2025                                     getFReg(fs)));
   2026                   break;
   2027 
   2028                case 0x11:  //D
   2029                   DIP("trunc.w.d %d, %d\n", fd, fs);
   2030                   t0 = newTemp(Ity_I32);
   2031 
   2032                   assign(t0, binop(Iop_F64toI32S, mkU32(0x3), getDReg(fs)));
   2033 
   2034                   putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
   2035                   break;
   2036 
   2037                default:
   2038                   goto decode_failure;
   2039 
   2040                }
   2041                break;
   2042             case 0x0E:  //CEIL.W.fmt
   2043                switch (fmt) {
   2044                case 0x10:  //S
   2045                   DIP("ceil.w.s %d, %d\n", fd, fs);
   2046                   putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2),
   2047                                     getFReg(fs)));
   2048                   break;
   2049 
   2050                case 0x11:  //D
   2051                   DIP("ceil.w.d %d, %d\n", fd, fs);
   2052                   t0 = newTemp(Ity_I32);
   2053 
   2054                   assign(t0, binop(Iop_F64toI32S, mkU32(0x2), getDReg(fs)));
   2055 
   2056                   putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
   2057                   break;
   2058 
   2059                default:
   2060                   goto decode_failure;
   2061 
   2062                }
   2063                break;
   2064             case 0x0A:  //CEIL.L.fmt
   2065                switch (fmt) {
   2066                case 0x10:  //S
   2067                   DIP("ceil.l.s %d, %d\n", fd, fs);
   2068                   goto decode_failure;
   2069 
   2070                case 0x11:  //D
   2071                   DIP("ceil.l.d %d, %d\n", fd, fs);
   2072 
   2073                   goto decode_failure;
   2074 
   2075                default:
   2076                   goto decode_failure;
   2077 
   2078                }
   2079                break;
   2080 
   2081             case 0x16:  //RSQRT.fmt
   2082                switch (fmt) {
   2083                case 0x10:
   2084                   {  //S
   2085                      DIP("rsqrt.s %d, %d\n", fd, fs);
   2086                      IRExpr *rm = get_IR_roundingmode();
   2087                      putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
   2088                                  unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)),
   2089                                  binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
   2090                                  getFReg(fs))))));
   2091                      break;
   2092                   }
   2093                case 0x11:
   2094                   {  //D
   2095                      DIP("rsqrt.d %d, %d\n", fd, fs);
   2096                      IRExpr *rm = get_IR_roundingmode();
   2097                      putDReg(fd, triop(Iop_DivF64, rm,
   2098                                  unop(Iop_ReinterpI64asF64,
   2099                                  mkU64(0x3FF0000000000000ULL)),
   2100                                  binop(Iop_SqrtF64, rm, getDReg(fs))));
   2101                      break;
   2102                   }
   2103                default:
   2104                   goto decode_failure;
   2105 
   2106                }
   2107                break;
   2108 
   2109             default:
   2110                if (dis_instr_CCondFmt(cins))
   2111                   break;
   2112                goto decode_failure;
   2113 
   2114             }
   2115 
   2116          }
   2117       }
   2118       break;      /*COP1 */
   2119    case 0x10:     /* COP0 */
   2120       if (rs == 0) { /* MFC0 */
   2121          DIP("mfc0 r%d, r%d, %d", rt, rd, sel);
   2122 
   2123          IRTemp   val  = newTemp(Ity_I32);
   2124          IRExpr** args = mkIRExprVec_2 (mkU32(rd), mkU32(sel));
   2125          IRDirty *d = unsafeIRDirty_1_N(val,
   2126                                         0,
   2127                                         "mips32_dirtyhelper_mfc0",
   2128                                         &mips32_dirtyhelper_mfc0,
   2129                                         args);
   2130 
   2131          stmt(IRStmt_Dirty(d));
   2132          putIReg(rt, mkexpr(val));
   2133       } else
   2134          goto decode_failure;
   2135       break;
   2136    case 0x31:     /* LWC1 */
   2137       /* Load Word to Floating Point - LWC1 (MIPS32) */
   2138       LOAD_STORE_PATTERN;
   2139       putFReg(ft, load(Ity_F32, mkexpr(t1)));
   2140 
   2141       DIP("lwc1 f%d, %d(r%d)", ft, imm, rs);
   2142       break;
   2143 
   2144    case 0x39:     /* SWC1 */
   2145       LOAD_STORE_PATTERN;
   2146       store(mkexpr(t1), getFReg(ft));
   2147       DIP("swc1 f%d, %d(r%d)", ft, imm, rs);
   2148       break;
   2149 
   2150    case 0x33:     /* PREF */
   2151       DIP("pref");
   2152       break;
   2153 
   2154    case 0x35:
   2155       /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
   2156       LOAD_STORE_PATTERN;
   2157 
   2158       t2 = newTemp(Ity_I32);
   2159       assign(t2, binop(Iop_Add32, getIReg(rs),
   2160                        mkU32(extend_s_16to32(imm + 4))));
   2161 
   2162 #if defined (_MIPSEL)
   2163       putFReg(ft, load(Ity_F32, mkexpr(t1)));
   2164       putFReg(ft + 1, load(Ity_F32, mkexpr(t2)));
   2165 #elif defined (_MIPSEB)
   2166       putFReg(ft + 1, load(Ity_F32, mkexpr(t1)));
   2167       putFReg(ft, load(Ity_F32, mkexpr(t2)));
   2168 #endif
   2169       DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs);
   2170       break;
   2171 
   2172    case 0x3D:
   2173       /* Store Doubleword from Floating Point - SDC1 */
   2174       LOAD_STORE_PATTERN;
   2175 
   2176       t2 = newTemp(Ity_I32);
   2177       assign(t2, binop(Iop_Add32, getIReg(rs),
   2178                        mkU32(extend_s_16to32(imm + 4))));
   2179 
   2180 #if defined (_MIPSEL)
   2181       store(mkexpr(t1), getFReg(ft));
   2182       store(mkexpr(t2), getFReg(ft + 1));
   2183 #elif defined (_MIPSEB)
   2184       store(mkexpr(t1), getFReg(ft + 1));
   2185       store(mkexpr(t2), getFReg(ft));
   2186 #endif
   2187       DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
   2188       break;
   2189 
   2190    case 0x23:     /* LW */
   2191       DIP("lw r%d, %d(r%d)", rt, imm, rs);
   2192       LOAD_STORE_PATTERN;
   2193       putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
   2194       break;
   2195 
   2196    case 0x20:     /* LB */
   2197       DIP("lb r%d, %d(r%d)", rt, imm, rs);
   2198       LOAD_STORE_PATTERN;
   2199       putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
   2200       break;
   2201 
   2202    case 0x24:     /* LBU */
   2203       DIP("lbu r%d, %d(r%d)", rt, imm, rs);
   2204       LOAD_STORE_PATTERN;
   2205       putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
   2206       break;
   2207 
   2208    case 0x21:     /* LH */
   2209       DIP("lh r%d, %d(r%d)", rt, imm, rs);
   2210       LOAD_STORE_PATTERN;
   2211       putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
   2212       break;
   2213 
   2214    case 0x25:     /* LHU */
   2215       DIP("lhu r%d, %d(r%d)", rt, imm, rs);
   2216       LOAD_STORE_PATTERN;
   2217       putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
   2218       break;
   2219 
   2220    case 0x0F:     /* LUI */
   2221       p = (imm << 16);
   2222       DIP("lui rt: %d, imm: %d, imm << 16: %d", rt, imm, p);
   2223       if ((vex_traceflags & VEX_TRACE_FE) && !mode64)
   2224          ppIRExpr(mkU32(p));
   2225       putIReg(rt, mkU32(p));
   2226       break;
   2227 
   2228    case 0x13:     /* COP1X */
   2229       switch (function) {
   2230       case 0x0: { /* LWXC1 */
   2231          /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
   2232          DIP("lwxc1 f%d, r%d(r%d) \n", fd, rt, rs);
   2233          t0 = newTemp(Ity_I32);
   2234          assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
   2235          putFReg(fd, load(Ity_F32, mkexpr(t0)));
   2236          break;
   2237       }
   2238 
   2239       case 0x1: { /* LDXC1 */
   2240          /* Load Doubleword  Indexed to Floating Point - LDXC1 (MIPS32r2) */
   2241          t0 = newTemp(Ity_I32);
   2242          assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
   2243 
   2244          t1 = newTemp(Ity_I32);
   2245          assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
   2246 
   2247 #if defined (_MIPSEL)
   2248          putFReg(fd, load(Ity_F32, mkexpr(t0)));
   2249          putFReg(fd + 1, load(Ity_F32, mkexpr(t1)));
   2250 #elif defined (_MIPSEB)
   2251          putFReg(fd + 1, load(Ity_F32, mkexpr(t0)));
   2252          putFReg(fd, load(Ity_F32, mkexpr(t1)));
   2253 #endif
   2254          DIP("ldxc1 f%d, r%d(r%d) \n", fd, rt, rs);
   2255          break;
   2256       }
   2257 
   2258       case 0x5:   // Load Doubleword Indexed Unaligned
   2259          // to Floating Point - LUXC1; MIPS32r2
   2260          DIP("luxc1 f%d, r%d(r%d) \n", fd, rt, rs);
   2261          t0 = newTemp(Ity_I64);
   2262          t1 = newTemp(Ity_I64);
   2263          assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
   2264          assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL)));
   2265          putFReg(fd, load(Ity_F64, mkexpr(t1)));
   2266          break;
   2267 
   2268       case 0x8: { /* SWXC1 */
   2269          /* Store Word Indexed from Floating Point - SWXC1 */
   2270          t0 = newTemp(Ity_I32);
   2271          assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
   2272 
   2273          store(mkexpr(t0), getFReg(fs));
   2274 
   2275          DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs);
   2276          break;
   2277       }
   2278       case 0x9: { /* SDXC1 */
   2279          /* Store Doubleword Indexed from Floating Point - SDXC1 */
   2280          t0 = newTemp(Ity_I32);
   2281          assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
   2282 
   2283          t1 = newTemp(Ity_I32);
   2284          assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
   2285 
   2286 #if defined (_MIPSEL)
   2287          store(mkexpr(t0), getFReg(fs));
   2288          store(mkexpr(t1), getFReg(fs + 1));
   2289 #elif defined (_MIPSEB)
   2290          store(mkexpr(t0), getFReg(fs + 1));
   2291          store(mkexpr(t1), getFReg(fs));
   2292 #endif
   2293 
   2294          DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
   2295          break;
   2296       }
   2297       case 0x0F: {
   2298          DIP("prefx");
   2299          break;
   2300       }
   2301       case 0x20:  { /* MADD.S */
   2302          DIP("madd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2303          IRExpr *rm = get_IR_roundingmode();
   2304          t1 = newTemp(Ity_F32);
   2305          assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
   2306                           getLoFromF64(tyF, getFReg(ft))));
   2307 
   2308          putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, mkexpr(t1),
   2309                                     getLoFromF64(tyF, getFReg(fmt)))));
   2310          break;   /* MADD.S */
   2311       }
   2312       case 0x21: { /* MADD.D */
   2313          DIP("madd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2314          IRExpr *rm = get_IR_roundingmode();
   2315          t1 = newTemp(Ity_F64);
   2316          assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
   2317 
   2318          putDReg(fd, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
   2319          break;   /* MADD.D */
   2320       }
   2321       case 0x28: { /* MSUB.S */
   2322          DIP("msub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2323          IRExpr *rm = get_IR_roundingmode();
   2324          t1 = newTemp(Ity_F32);
   2325          assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
   2326                           getLoFromF64(tyF, getFReg(ft))));
   2327 
   2328          putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
   2329                      mkexpr(t1), getLoFromF64(tyF, getFReg(fmt)))));
   2330          break;   /* MSUB.S */
   2331       }
   2332       case 0x29: { /* MSUB.D */
   2333          DIP("msub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2334          IRExpr *rm = get_IR_roundingmode();
   2335          t1 = newTemp(Ity_F64);
   2336          assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
   2337 
   2338          putDReg(fd, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
   2339          break;   /* MSUB.D */
   2340       }
   2341       case 0x30: { /* NMADD.S */
   2342          DIP("nmadd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2343          IRExpr *rm = get_IR_roundingmode();
   2344          t1 = newTemp(Ity_F32);
   2345          t2 = newTemp(Ity_F32);
   2346          assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
   2347                 getLoFromF64(tyF, getFReg(ft))));
   2348 
   2349          assign(t2, triop(Iop_AddF32, rm, mkexpr(t1),
   2350                           getLoFromF64(tyF, getFReg(fmt))));
   2351 
   2352          putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
   2353          break;   /* NMADD.S */
   2354       }
   2355       case 0x31: { /* NMADD.D */
   2356          DIP("nmadd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2357          IRExpr *rm = get_IR_roundingmode();
   2358          t1 = newTemp(Ity_F64);
   2359          t2 = newTemp(Ity_F64);
   2360          assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
   2361 
   2362          assign(t2, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
   2363          putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
   2364          break;   /* NMADD.D */
   2365       }
   2366       case 0x38: { /* NMSUBB.S */
   2367          DIP("nmsub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2368          IRExpr *rm = get_IR_roundingmode();
   2369          t1 = newTemp(Ity_F32);
   2370          t2 = newTemp(Ity_F32);
   2371          assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
   2372                           getLoFromF64(tyF, getFReg(ft))));
   2373 
   2374          assign(t2, triop(Iop_SubF32, rm, mkexpr(t1), getLoFromF64(tyF,
   2375                                                       getFReg(fmt))));
   2376 
   2377          putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
   2378          break;   /* NMSUBB.S */
   2379       }
   2380       case 0x39: { /* NMSUBB.D */
   2381          DIP("nmsub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
   2382          IRExpr *rm = get_IR_roundingmode();
   2383          t1 = newTemp(Ity_F64);
   2384          t2 = newTemp(Ity_F64);
   2385          assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
   2386 
   2387          assign(t2, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
   2388          putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
   2389          break;   /* NMSUBB.D */
   2390       }
   2391 
   2392       default:
   2393          goto decode_failure;
   2394       }
   2395       break;
   2396 
   2397    case 0x22:     /* LWL */
   2398 
   2399       DIP("lwl r%d, %d(r%d)", rt, imm, rs);
   2400       {
   2401          /* t1 = addr */
   2402          t1 = newTemp(Ity_I32);
   2403 #if defined (_MIPSEL)
   2404          assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   2405 #elif defined (_MIPSEB)
   2406          assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
   2407                                      mkU32(extend_s_16to32(imm)))));
   2408 #endif
   2409 
   2410          /* t2 = word addr */
   2411          /* t4 = addr mod 4 */
   2412          LWX_SWX_PATTERN;
   2413 
   2414          /* t3 = word content - shifted */
   2415          t3 = newTemp(Ity_I32);
   2416          assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
   2417                     binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
   2418                     mkU8(3)))));
   2419 
   2420          /* rt content  - adjusted */
   2421          t5 = newTemp(Ity_I32);
   2422          assign(t5, binop(Iop_And32, getIReg(rt), binop(Iop_Shr32,
   2423                     mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32,
   2424                     binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), mkU8(0x3))))));
   2425 
   2426          putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
   2427       }
   2428       break;
   2429 
   2430    case 0x26:     /* LWR */
   2431 
   2432       DIP("lwr r%d, %d(r%d)", rt, imm, rs);
   2433       {
   2434          /* t1 = addr */
   2435          t1 = newTemp(Ity_I32);
   2436 #if defined (_MIPSEL)
   2437          assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   2438 #elif defined (_MIPSEB)
   2439          assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
   2440                                      mkU32(extend_s_16to32(imm)))));
   2441 #endif
   2442 
   2443          /* t2 = word addr */
   2444          /* t4 = addr mod 4 */
   2445          LWX_SWX_PATTERN;
   2446 
   2447          /* t3 = word content - shifted */
   2448          t3 = newTemp(Ity_I32);
   2449          assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
   2450                     narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
   2451                     mkU8(3)))));
   2452 
   2453          /* rt content  - adjusted */
   2454          t5 = newTemp(Ity_I32);
   2455          assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
   2456                     binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
   2457                           binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
   2458 
   2459          putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
   2460       }
   2461       break;
   2462 
   2463    case 0x2B:     /* SW */
   2464       DIP("sw r%d, %d(r%d)", rt, imm, rs);
   2465       LOAD_STORE_PATTERN;
   2466       store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
   2467       break;
   2468 
   2469    case 0x28:     /* SB */
   2470       DIP("sb r%d, %d(r%d)", rt, imm, rs);
   2471       LOAD_STORE_PATTERN;
   2472       store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
   2473       break;
   2474 
   2475    case 0x29:     /* SH */
   2476       DIP("sh r%d, %d(r%d)", rt, imm, rs);
   2477       LOAD_STORE_PATTERN;
   2478       store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
   2479       break;
   2480 
   2481    case 0x2A:     /* SWL */
   2482 
   2483       DIP("swl r%d, %d(r%d)", rt, imm, rs);
   2484       {
   2485          /* t1 = addr */
   2486          t1 = newTemp(Ity_I32);
   2487 #if defined (_MIPSEL)
   2488          assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   2489 #elif defined (_MIPSEB)
   2490          assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
   2491                                      mkU32(extend_s_16to32(imm)))));
   2492 #endif
   2493 
   2494          /* t2 = word addr */
   2495          /* t4 = addr mod 4 */
   2496          LWX_SWX_PATTERN;
   2497 
   2498          /* t3 = rt content - shifted */
   2499          t3 = newTemp(Ity_I32);
   2500          assign(t3, binop(Iop_Shr32, getIReg(rt), narrowTo(Ity_I8,
   2501                     binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
   2502                     mkU8(3)))));
   2503 
   2504          /* word content  - adjusted */
   2505          t5 = newTemp(Ity_I32);
   2506          t6 = newTemp(Ity_I32);
   2507          t7 = newTemp(Ity_I32);
   2508          t8 = newTemp(Ity_I32);
   2509 
   2510          // neg(shr(0xFFFFFFFF, mul(sub(3,n), 8)))
   2511          assign(t5, binop(Iop_Mul32, binop(Iop_Sub32, mkU32(0x3), mkexpr(t4)),
   2512                           mkU32(0x8)));
   2513 
   2514          assign(t6, binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
   2515                                                         mkexpr(t5))));
   2516          assign(t7, binop(Iop_Xor32, mkU32(0xFFFFFFFF), mkexpr(t6)));
   2517          assign(t8, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), mkexpr(t7)));
   2518          store(mkexpr(t2), binop(Iop_Or32, mkexpr(t8), mkexpr(t3)));
   2519       }
   2520       break;
   2521 
   2522    case 0x2E:     /* SWR */
   2523 
   2524       DIP("swr r%d, %d(r%d)", rt, imm, rs);
   2525       {
   2526          /* t1 = addr */
   2527          t1 = newTemp(Ity_I32);
   2528 #if defined (_MIPSEL)
   2529          assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   2530 #elif defined (_MIPSEB)
   2531          assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
   2532                                      mkU32(extend_s_16to32(imm)))));
   2533 #endif
   2534 
   2535          /* t2 = word addr */
   2536          /* t4 = addr mod 4 */
   2537          LWX_SWX_PATTERN;
   2538 
   2539          /* t3 = rt content - shifted */
   2540          t3 = newTemp(Ity_I32);
   2541          assign(t3, binop(Iop_Shl32, getIReg(rt), narrowTo(Ity_I8,
   2542                     binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
   2543 
   2544          /* word content  - adjusted */
   2545          t5 = newTemp(Ity_I32);
   2546          assign(t5, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), unop(Iop_Not32,
   2547                     binop(Iop_Shl32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
   2548                           binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
   2549 
   2550          store(mkexpr(t2), binop(Iop_Xor32, mkexpr(t5), mkexpr(t3)));
   2551       }
   2552       break;
   2553 
   2554    case 0x1C:     /*Special2 */
   2555       switch (function) {
   2556       case 0x02: { /* MUL */
   2557          DIP("mul r%d, r%d, r%d", rd, rs, rt);
   2558          putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
   2559          break;
   2560       }
   2561 
   2562       case 0x00: { /* MADD */
   2563          DIP("madd r%d, r%d", rs, rt);
   2564          t1 = newTemp(Ity_I32);
   2565          t2 = newTemp(Ity_I32);
   2566          t3 = newTemp(Ity_I64);
   2567          t4 = newTemp(Ity_I32);
   2568          t5 = newTemp(Ity_I32);
   2569          t6 = newTemp(Ity_I32);
   2570 
   2571          assign(t1, getHI());
   2572          assign(t2, getLO());
   2573 
   2574          assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
   2575 
   2576          assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
   2577                                                       mkexpr(t3))));
   2578 
   2579          assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
   2580                                      unop(Iop_64to32, mkexpr(t3)))));
   2581          assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
   2582 
   2583          putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
   2584          putLO(mkexpr(t4));
   2585          break;
   2586       }
   2587 
   2588       case 0x01: { /* MADDU */
   2589          DIP("maddu r%d, r%d", rs, rt);
   2590          t1 = newTemp(Ity_I32);
   2591          t2 = newTemp(Ity_I32);
   2592          t3 = newTemp(Ity_I64);
   2593          t4 = newTemp(Ity_I32);
   2594          t5 = newTemp(Ity_I32);
   2595          t6 = newTemp(Ity_I32);
   2596 
   2597          assign(t1, getHI());
   2598          assign(t2, getLO());
   2599 
   2600          assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
   2601 
   2602          assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
   2603                                                       mkexpr(t3))));
   2604          assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
   2605                                      unop(Iop_64to32, mkexpr(t3)))));
   2606          assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
   2607 
   2608          putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
   2609          putLO(mkexpr(t4));
   2610          break;
   2611       }
   2612 
   2613       case 0x04: { /* MSUB */
   2614          DIP("msub r%d, r%d", rs, rt);
   2615          t1 = newTemp(Ity_I32);
   2616          t2 = newTemp(Ity_I32);
   2617          t3 = newTemp(Ity_I64);
   2618          t4 = newTemp(Ity_I32);
   2619          t5 = newTemp(Ity_I32);
   2620          t6 = newTemp(Ity_I32);
   2621 
   2622          assign(t1, getHI());
   2623          assign(t2, getLO());
   2624 
   2625          assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
   2626          assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
   2627 
   2628          //if lo<lo(mul) hi = hi - 1
   2629          assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
   2630                                            mkexpr(t4))));
   2631 
   2632          assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)), mkexpr(t1),
   2633                                  binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
   2634 
   2635          putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
   2636          putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
   2637          break;
   2638       }
   2639 
   2640       case 0x05: { /* MSUBU */
   2641          DIP("msubu r%d, r%d", rs, rt);
   2642          t1 = newTemp(Ity_I32);
   2643          t2 = newTemp(Ity_I32);
   2644          t3 = newTemp(Ity_I64);
   2645          t4 = newTemp(Ity_I32);
   2646          t5 = newTemp(Ity_I32);
   2647          t6 = newTemp(Ity_I32);
   2648 
   2649          assign(t1, getHI());
   2650          assign(t2, getLO());
   2651 
   2652          assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
   2653          assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
   2654 
   2655          //if lo<lo(mul) hi = hi - 1
   2656          assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
   2657                                            mkexpr(t4))));
   2658 
   2659          assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)),
   2660                     mkexpr(t1), binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
   2661 
   2662          putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
   2663          putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
   2664          break;
   2665       }
   2666 
   2667       case 0x20: { /* CLZ */
   2668          DIP("clz r%d, r%d", rd, rs);
   2669          t1 = newTemp(Ity_I32);
   2670          assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
   2671                                            mkU32(0))));
   2672          putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   2673                      unop(Iop_Clz32, getIReg(rs)), mkU32(0x00000020)));
   2674          break;
   2675       }
   2676 
   2677       case 0x21: { /* CLO */
   2678          DIP("clo r%d, r%d", rd, rs);
   2679          t1 = newTemp(Ity_I32);
   2680          assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
   2681                                            mkU32(0xffffffff))));
   2682          putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   2683                      unop(Iop_Clz32, unop(Iop_Not32, getIReg(rs))),
   2684                      mkU32(0x00000020)));
   2685          break;
   2686       }
   2687 
   2688       default:
   2689          goto decode_failure;
   2690       }
   2691       break;
   2692 
   2693    case 0x1F:     /*Special3 */
   2694       switch (function) {
   2695       case 0x3B:
   2696           /*RDHWR*/ {
   2697             DIP("rdhwr r%d, r%d", rt, rd);
   2698             if (rd == 29) {
   2699                putIReg(rt, getULR());
   2700             } else
   2701                goto decode_failure;
   2702             break;
   2703          }
   2704       case 0x04:
   2705           /*INS*/ msb = get_msb(cins);
   2706          lsb = get_lsb(cins);
   2707 
   2708          size = msb - lsb + 1;
   2709 
   2710          vassert(lsb + size <= 32);
   2711          vassert(lsb + size > 0);
   2712 
   2713          DIP("ins size:%d msb:%d lsb:%d", size, msb, lsb);
   2714          /*put size bits from rs at the pos in temporary */
   2715          t0 = newTemp(Ity_I32);
   2716          t3 = newTemp(Ity_I32);
   2717          /*shift left for 32 - size to clear leading bits and get zeros
   2718            at the end */
   2719          assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - size)));
   2720          /*now set it at pos */
   2721          t1 = newTemp(Ity_I32);
   2722          assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
   2723 
   2724          if (lsb > 0) {
   2725             t2 = newTemp(Ity_I32);
   2726             /*clear everything but lower pos bits from rt */
   2727             assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(32 - lsb)));
   2728             assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
   2729          }
   2730 
   2731          if (msb < 31) {
   2732             t4 = newTemp(Ity_I32);
   2733             /*clear everything but upper msb + 1 bits from rt */
   2734             assign(t4, binop(Iop_Shr32, getIReg(rt), mkU8(msb + 1)));
   2735             t5 = newTemp(Ity_I32);
   2736             assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
   2737 
   2738             /*now combine these registers */
   2739             if (lsb > 0) {
   2740                t6 = newTemp(Ity_I32);
   2741                assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
   2742                putIReg(rt, binop(Iop_Or32, mkexpr(t6), mkexpr(t3)));
   2743             } else {
   2744                putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t5)));
   2745             }
   2746          }
   2747 
   2748          else {
   2749             putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t3)));
   2750 
   2751          }
   2752          break;
   2753 
   2754       case 0x00:
   2755          /*EXT*/ msb = get_msb(cins);
   2756          lsb = get_lsb(cins);
   2757          size = msb + 1;
   2758          DIP("ext size:%d msb:%d lsb:%d", size, msb, lsb);
   2759          vassert(lsb + size <= 32);
   2760          vassert(lsb + size > 0);
   2761          /*put size bits from rs at the top of in temporary */
   2762          if (lsb + size < 32) {
   2763             t0 = newTemp(Ity_I32);
   2764             assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - lsb - size)));
   2765             putIReg(rt, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size)));
   2766          } else {
   2767             putIReg(rt, binop(Iop_Shr32, getIReg(rs), mkU8(32 - size)));
   2768 
   2769          }
   2770          break;
   2771 
   2772       case 0x20:
   2773          /*BSHFL*/ switch (sa) {
   2774          case 0x10:
   2775              /*SEB*/ DIP("seb r%d, r%d", rd, rt);
   2776             putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
   2777             break;
   2778 
   2779          case 0x18:
   2780              /*SEH*/ DIP("seh r%d, r%d", rd, rt);
   2781             putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
   2782             break;
   2783 
   2784          case 0x02:
   2785              /*WSBH*/ DIP("wsbh r%d, r%d", rd, rt);
   2786             t0 = newTemp(Ity_I32);
   2787             t1 = newTemp(Ity_I32);
   2788             t2 = newTemp(Ity_I32);
   2789             t3 = newTemp(Ity_I32);
   2790             assign(t0, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
   2791                                         mkU32(0x00FF0000)), mkU8(0x8)));
   2792             assign(t1, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
   2793                        mkU32(0xFF000000)), mkU8(0x8)));
   2794             assign(t2, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
   2795                        mkU32(0x000000FF)), mkU8(0x8)));
   2796             assign(t3, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
   2797                        mkU32(0x0000FF00)), mkU8(0x8)));
   2798             putIReg(rd, binop(Iop_Or32, binop(Iop_Or32, mkexpr(t0),
   2799                         mkexpr(t1)), binop(Iop_Or32, mkexpr(t2), mkexpr(t3))));
   2800             break;
   2801 
   2802          default:
   2803             goto decode_failure;
   2804 
   2805          }
   2806          break;
   2807        /*BSHFL*/ default:
   2808          goto decode_failure;
   2809 
   2810       }
   2811       break;      /*Special3 */
   2812 
   2813    case 0x3B:
   2814       if (0x3B == function && (archinfo->hwcaps & VEX_PRID_COMP_BROADCOM)) {
   2815           /*RDHWR*/
   2816             DIP("rdhwr r%d, r%d", rt, rd);
   2817             if (rd == 29) {
   2818                putIReg(rt, getULR());
   2819             } else
   2820                goto decode_failure;
   2821             break;
   2822       } else {
   2823          goto decode_failure;
   2824       }
   2825 
   2826    case 0x00:     /*Special */
   2827 
   2828       switch (function) {
   2829       case 0x1: {
   2830          UInt mov_cc = get_mov_cc(cins);
   2831          if (tf == 0) { /* MOVF */
   2832             DIP("movf r%d, r%d, %d", rd, rs, mov_cc);
   2833             {
   2834                t1 = newTemp(Ity_I32);
   2835                t2 = newTemp(Ity_I32);
   2836                t3 = newTemp(Ity_I32);
   2837                t4 = newTemp(Ity_I32);
   2838 
   2839                assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   2840                                                  mkU32(mov_cc))));
   2841                assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   2842                           binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   2843                           mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
   2844                           binop(Iop_Shr32, getFCSR(), mkU8(23)),
   2845                           mkU32(0x1))));
   2846 
   2847                assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   2848                                                  mkexpr(t2))));
   2849                assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   2850                           getIReg(rd), getIReg(rs)));
   2851                putIReg(rd, mkexpr(t4));
   2852             }
   2853          } else if (tf == 1) {   /* MOVT */
   2854             DIP("movt r%d, r%d, %d", rd, rs, mov_cc);
   2855             {
   2856                t1 = newTemp(Ity_I32);
   2857                t2 = newTemp(Ity_I32);
   2858                t3 = newTemp(Ity_I32);
   2859                t4 = newTemp(Ity_I32);
   2860 
   2861                assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
   2862                                                  mkU32(mov_cc))));
   2863                assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
   2864                           binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
   2865                           mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
   2866                           binop(Iop_Shr32, getFCSR(), mkU8(23)),
   2867                           mkU32(0x1))));
   2868 
   2869                assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
   2870                                                  mkexpr(t2))));
   2871                assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
   2872                           getIReg(rd), getIReg(rs)));
   2873                putIReg(rd, mkexpr(t4));
   2874             }
   2875          }
   2876          break;
   2877       }
   2878       case 0x0A: {
   2879          /* MOVZ */
   2880          DIP("movz r%d, r%d, r%d", rd, rs, rt);
   2881          t1 = newTemp(ty);
   2882          t2 = newTemp(ty);
   2883          {
   2884             assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
   2885                                               mkU32(0x0))));
   2886             assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
   2887                                               mkU32(0x0))));
   2888             putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
   2889                         mkexpr(t1)), binop(Iop_And32, getIReg(rd),
   2890                         mkexpr(t2))));
   2891          }
   2892          break;
   2893       }
   2894 
   2895       case 0x0B: {
   2896          /* MOVN */
   2897          DIP("movn r%d, r%d, r%d", rd, rs, rt);
   2898          t1 = newTemp(ty);
   2899          t2 = newTemp(ty);
   2900          {
   2901             assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
   2902                                               mkU32(0x0))));
   2903             assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
   2904                                               mkU32(0x0))));
   2905             putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
   2906                         mkexpr(t2)), binop(Iop_And32, getIReg(rd),
   2907                         mkexpr(t1))));
   2908          }
   2909          break;
   2910       }
   2911 
   2912       case 0x18:  /* MULT */
   2913          DIP("mult r%d, r%d", rs, rt);
   2914          t2 = newTemp(Ity_I64);
   2915 
   2916          assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
   2917                           mkNarrowTo32(ty, getIReg(rt))));
   2918 
   2919          putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
   2920          putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
   2921          break;
   2922 
   2923       case 0x19:  /* MULTU */
   2924          DIP("multu r%d, r%d", rs, rt);
   2925          t2 = newTemp(Ity_I64);
   2926 
   2927          assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
   2928                                        mkNarrowTo32(ty, getIReg(rt))));
   2929 
   2930          putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
   2931          putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
   2932          break;
   2933 
   2934       case 0x20:  /* ADD */
   2935          DIP("add r%d, r%d, r%d", rd, rs, rt);
   2936          {
   2937             t2 = newTemp(Ity_I32);
   2938 
   2939             assign(t2, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
   2940             putIReg(rd, mkexpr(t2));
   2941          }
   2942          break;
   2943 
   2944       case 0x1A:  /* DIV */
   2945          DIP("div r%d, r%d", rs, rt);
   2946          {
   2947             t1 = newTemp(Ity_I64);
   2948             t2 = newTemp(Ity_I64);
   2949 
   2950             assign(t1, unop(Iop_32Sto64, getIReg(rs)));
   2951             assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt)));
   2952 
   2953             putHI(unop(Iop_64HIto32, mkexpr(t2)));
   2954             putLO(unop(Iop_64to32, mkexpr(t2)));
   2955          }
   2956          break;
   2957 
   2958       case 0x1B:  /* DIVU */
   2959          DIP("divu r%d, r%d", rs, rt);
   2960          {
   2961             t1 = newTemp(Ity_I64);
   2962             t2 = newTemp(Ity_I64);
   2963             assign(t1, unop(Iop_32Uto64, getIReg(rs)));
   2964             assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt)));
   2965             putHI(unop(Iop_64HIto32, mkexpr(t2)));
   2966             putLO(unop(Iop_64to32, mkexpr(t2)));
   2967          }
   2968          break;
   2969 
   2970       case 0x10:  /* MFHI */
   2971          DIP("mfhi r%d", rd);
   2972          putIReg(rd, getHI());
   2973          break;
   2974 
   2975       case 0x11:  /* MTHI */
   2976          DIP("mthi r%d", rs);
   2977          putHI(getIReg(rs));
   2978          break;
   2979 
   2980       case 0x12:  /* MFLO */
   2981          DIP("mflo r%d", rd);
   2982          putIReg(rd, getLO());
   2983          break;
   2984 
   2985       case 0x13:  /* MTLO */
   2986          DIP("mtlo r%d", rs);
   2987          putLO(getIReg(rs));
   2988          break;
   2989 
   2990       case 0x21:  /* ADDU */
   2991          DIP("addu r%d, r%d, r%d", rd, rs, rt);
   2992          ALU_PATTERN(Iop_Add32);
   2993          break;
   2994 
   2995       case 0x22:  /* SUB */
   2996          DIP("sub r%d, r%d, r%d", rd, rs, rt);
   2997          ALU_PATTERN(Iop_Sub32);
   2998          break;
   2999 
   3000       case 0x23:  /* SUBU */
   3001          DIP("subu r%d, r%d, r%d", rd, rs, rt);
   3002          ALU_PATTERN(Iop_Sub32);
   3003          break;
   3004 
   3005       case 0x24:  /* AND */
   3006          DIP("and r%d, r%d, r%d", rd, rs, rt);
   3007          ALU_PATTERN(Iop_And32);
   3008          break;
   3009 
   3010       case 0x25:  /* OR */
   3011          DIP("or r%d, r%d, r%d", rd, rs, rt);
   3012          ALU_PATTERN(Iop_Or32);
   3013          break;
   3014 
   3015       case 0x26:  /* XOR */
   3016          DIP("xor r%d, r%d, r%d", rd, rs, rt);
   3017          ALU_PATTERN(Iop_Xor32);
   3018          break;
   3019 
   3020       case 0x27:  /* NOR */
   3021          DIP("nor r%d, r%d, r%d", rd, rs, rt);
   3022          putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),getIReg(rt))));
   3023          break;
   3024 
   3025       case 0x08:  /* JR */
   3026          DIP("jr r%d", rs);
   3027          t0 = newTemp(ty);
   3028          assign(t0, getIReg(rs));
   3029          lastn = mkexpr(t0);
   3030          break;
   3031 
   3032       case 0x09:  /* JALR */
   3033          DIP("jalr r%d r%d", rd, rs);
   3034          putIReg(rd, mkU32(guest_PC_curr_instr + 8));
   3035          t0 = newTemp(Ity_I32);
   3036          assign(t0, getIReg(rs));
   3037          lastn = mkexpr(t0);
   3038          break;
   3039 
   3040       case 0x0C:  /* SYSCALL */
   3041          DIP("syscall");
   3042          putPC(mkU32(guest_PC_curr_instr + 4));
   3043          dres.jk_StopHere = Ijk_Sys_syscall;
   3044          dres.whatNext    = Dis_StopHere;
   3045          break;
   3046 
   3047       case 0x2A:  /* SLT */
   3048          DIP("slt r%d, r%d, r%d", rd, rs, rt);
   3049          putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
   3050                                       getIReg(rt))));
   3051          break;
   3052 
   3053       case 0x2B:  /* SLTU */
   3054          DIP("sltu r%d, r%d, r%d", rd, rs, rt);
   3055          putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
   3056                                       getIReg(rt))));
   3057          break;
   3058 
   3059       case 0x00:
   3060          /* SLL */
   3061          DIP("sll r%d, r%d, %d", rd, rt, sa);
   3062          SXX_PATTERN(Iop_Shl32);
   3063          break;
   3064 
   3065       case 0x04:  /* SLLV */
   3066          DIP("sllv r%d, r%d, r%d", rd, rt, rs);
   3067          SXXV_PATTERN(Iop_Shl32);
   3068          break;
   3069 
   3070       case 0x03:  /* SRA */
   3071          DIP("sra r%d, r%d, %d", rd, rt, sa);
   3072          SXX_PATTERN(Iop_Sar32);
   3073          break;
   3074 
   3075       case 0x07:  /* SRAV */
   3076          DIP("srav r%d, r%d, r%d", rd, rt, rs);
   3077          SXXV_PATTERN(Iop_Sar32);
   3078          break;
   3079 
   3080       case 0x02: {  /* SRL */
   3081          rot = get_rot(cins);
   3082          if (rot) {
   3083             DIP("rotr r%d, r%d, %d", rd, rt, sa);
   3084             putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
   3085                         getIReg(rt)), sa), False));
   3086          } else {
   3087             DIP("srl r%d, r%d, %d", rd, rt, sa);
   3088             SXX_PATTERN(Iop_Shr32);
   3089          }
   3090       break;
   3091       }
   3092 
   3093       case 0x06: {
   3094          rot = get_rotv(cins);
   3095          if (rot) {
   3096             DIP("rotrv r%d, r%d, r%d", rd, rt, rs);
   3097             putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
   3098                         getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))),False));
   3099             break;
   3100          } else {
   3101             /* SRLV */
   3102             DIP("srlv r%d, r%d, r%d", rd, rt, rs);
   3103             SXXV_PATTERN(Iop_Shr32);
   3104             break;
   3105          }
   3106       }
   3107 
   3108       case 0x0D:  /* BREAK */
   3109          DIP("Info: Breakpoint...code = %d", trap_code);
   3110          jmp_lit(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
   3111          vassert(dres.whatNext == Dis_StopHere);
   3112          break;
   3113 
   3114       case 0x30: { /* TGE */
   3115          /*tge */ DIP("tge r%d, r%d %d", rs, rt, trap_code);
   3116          stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rt), getIReg (rs)),
   3117                             Ijk_SigTRAP,
   3118                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3119          break;
   3120       }
   3121       case 0x31: { /* TGEU */
   3122          /*tgeu */ DIP("tgeu r%d, r%d %d", rs, rt, trap_code);
   3123          stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rt), getIReg (rs)),
   3124                             Ijk_SigTRAP,
   3125                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3126          break;
   3127       }
   3128       case 0x32: { /* TLT */
   3129          /*tlt */ DIP("tlt r%d, r%d %d", rs, rt, trap_code);
   3130          stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), getIReg (rt)),
   3131                             Ijk_SigTRAP,
   3132                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3133          break;
   3134       }
   3135       case 0x33: { /* TLTU */
   3136          /*tltu */ DIP("tltu r%d, r%d %d", rs, rt, trap_code);
   3137          stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), getIReg (rt)),
   3138                             Ijk_SigTRAP,
   3139                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3140          break;
   3141       }
   3142       case 0x34: { /* TEQ */
   3143          /*teq */ DIP("teq r%d, r%d %d", rs, rt, trap_code);
   3144          stmt (IRStmt_Exit(binop (Iop_CmpEQ32, getIReg (rs), getIReg (rt)),
   3145                Ijk_SigTRAP, IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3146          break;
   3147       }
   3148       case 0x36: { /* TNE */
   3149          /*tne */ DIP("tne r%d, r%d %d", rs, rt, trap_code);
   3150          stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), getIReg (rt)),
   3151                             Ijk_SigTRAP,
   3152                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3153          break;
   3154       }
   3155       case 0x0F: {
   3156          /*SYNC*/ DIP("sync r%d, r%d, %d", rt, rd, sel);
   3157          lsb = get_lsb(cins);
   3158          IRDirty *d = unsafeIRDirty_0_N(0,
   3159                                         "mips32_dirtyhelper_sync",
   3160                                         &mips32_dirtyhelper_sync,
   3161                                         mkIRExprVec_1
   3162                                         (mkU32(lsb)));
   3163 
   3164          d->needsBBP = False;
   3165          d->nFxState = 0;
   3166 
   3167          stmt(IRStmt_Dirty(d));
   3168          break;
   3169       }
   3170 
   3171       default:
   3172          goto decode_failure;
   3173       }
   3174       break;
   3175 
   3176    case 0x01:     /* Regimm */
   3177 
   3178       switch (rt) {
   3179       case 0x01:  /* BGEZ */
   3180          DIP("bgez r%d, %d", rs, imm);
   3181          dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
   3182                            mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
   3183          break;
   3184 
   3185       case 0x03:  /* BGEZL */
   3186          DIP("bgezl r%d, %d", rs, imm);
   3187          lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
   3188                                    getIReg(rs), mode64 ?
   3189                                       mkU64(0x8000000000000000ULL)
   3190                                       :mkU32(0x80000000)),
   3191                                    mkU32(0x0)), imm);
   3192          break;
   3193 
   3194       case 0x00:  /* BLTZ */
   3195          DIP("bltz r%d, %d", rs, imm);
   3196          dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
   3197                     mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
   3198          break;
   3199 
   3200       case 0x02:  /* BLTZL */
   3201          DIP("bltzl r%d, %d", rs, imm);
   3202          lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
   3203                                    getIReg(rs), mkU32(0x80000000)),
   3204                                    mkU32(0x80000000)), imm);
   3205          break;
   3206 
   3207       case 0x10:  /* BLTZAL */
   3208          DIP("bltzal r%d, %d", rs, imm);
   3209          dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
   3210                     mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
   3211          break;
   3212 
   3213       case 0x12:  /* BLTZALL */
   3214          DIP("bltzall r%d, %d", rs, imm);
   3215          putIReg(31, mkU32(guest_PC_curr_instr + 8));
   3216          lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
   3217                                    getIReg(rs), mkU32(0x80000000)),
   3218                                                 mkU32(0x80000000)), imm);
   3219          break;
   3220 
   3221       case 0x11:  /* BGEZAL */
   3222          DIP("bgezal r%d, %d", rs, imm);
   3223          dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
   3224                     mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
   3225          break;
   3226 
   3227       case 0x13:  /* BGEZALL */
   3228          DIP("bgezall r%d, %d", rs, imm);
   3229          putIReg(31, mkU32(guest_PC_curr_instr + 8));
   3230          lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
   3231                                    getIReg(rs), mkU32(0x80000000)),
   3232                                    mkU32(0x0)), imm);
   3233          break;
   3234 
   3235       case 0x08: { /* TGEI */
   3236          /*tgei */ DIP("tgei r%d, %d %d", rs, imm, trap_code);
   3237          stmt (IRStmt_Exit (binop (Iop_CmpLT32S, mkU32 (imm), getIReg (rs)),
   3238                             Ijk_SigTRAP,
   3239                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3240          break;
   3241       }
   3242       case 0x09: { /* TGEIU */
   3243          /*tqeiu */ DIP("tgeiu r%d, %d %d", rs, imm, trap_code);
   3244          stmt (IRStmt_Exit (binop (Iop_CmpLT32U, mkU32 (imm), getIReg (rs)),
   3245                             Ijk_SigTRAP,
   3246                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3247          break;
   3248       }
   3249       case 0x0A: { /* TLTI */
   3250          /*tlti */ DIP("tlti r%d, %d %d", rs, imm, trap_code);
   3251          stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), mkU32 (imm)),
   3252                             Ijk_SigTRAP,
   3253                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3254          break;
   3255       }
   3256       case 0x0B: { /* TLTIU */
   3257          /*tltiu */ DIP("tltiu r%d, %d %d", rs, imm, trap_code);
   3258          stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), mkU32 (imm)),
   3259                             Ijk_SigTRAP,
   3260                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3261          break;
   3262       }
   3263       case 0x0C: { /* TEQI */
   3264          /*teqi */ DIP("teqi r%d, %d %d", rs, imm, trap_code);
   3265          stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), mkU32 (imm)),
   3266                             Ijk_SigTRAP,
   3267                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3268          break;
   3269       }
   3270       case 0x0E: { /* TNEI */
   3271          /*tnei */ DIP("tnei r%d, %d %d", rs, imm, trap_code);
   3272          stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), mkU32 (imm)),
   3273                             Ijk_SigTRAP,
   3274                             IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
   3275          break;
   3276       }
   3277       case 0x1F:
   3278           /*SYNCI*/
   3279              //Just ignore it
   3280              break;
   3281 
   3282       default:
   3283          goto decode_failure;
   3284       }
   3285       break;
   3286 
   3287    case 0x04:
   3288       DIP("beq r%d, r%d, %d", rs, rt, imm);
   3289       dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
   3290                               imm, &bstmt);
   3291       break;
   3292 
   3293    case 0x14:
   3294       DIP("beql r%d, r%d, %d", rs, rt, imm);
   3295       lastn = dis_branch_likely(binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
   3296                                       imm);
   3297       break;
   3298 
   3299    case 0x05:
   3300       DIP("bne r%d, r%d, %d", rs, rt, imm);
   3301       dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
   3302                               imm, &bstmt);
   3303       break;
   3304 
   3305    case 0x15:
   3306       DIP("bnel r%d, r%d, %d", rs, rt, imm);
   3307       lastn =
   3308           dis_branch_likely(binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), imm);
   3309       break;
   3310 
   3311    case 0x07:     /* BGTZ */
   3312       DIP("bgtz r%d, %d", rs, imm);
   3313       dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
   3314                              mkU32(0x00))), imm, &bstmt);
   3315       break;
   3316 
   3317    case 0x17:     /* BGTZL */
   3318       DIP("bgtzl r%d, %d", rs, imm);
   3319       lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x00)),
   3320                                       imm);
   3321       break;
   3322 
   3323    case 0x06:     /* BLEZ */
   3324       DIP("blez r%d, %d", rs, imm);
   3325       dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
   3326                              &bstmt);
   3327       break;
   3328 
   3329    case 0x16:     /* BLEZL */
   3330       DIP("blezl r%d, %d", rs, imm);
   3331       lastn = dis_branch_likely(unop(Iop_Not1, (binop(Iop_CmpLE32S,
   3332                                      getIReg(rs), mkU32(0x0)))), imm);
   3333       break;
   3334 
   3335    case 0x08:     /* ADDI TODO: Check this */
   3336       DIP("addi r%d, r%d, %d", rt, rs, imm);
   3337       putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   3338       break;
   3339 
   3340    case 0x09:     /* ADDIU */
   3341       DIP("addiu r%d, r%d, %d", rt, rs, imm);
   3342       putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
   3343       break;
   3344 
   3345    case 0x0C:     /* ANDI */
   3346       DIP("andi r%d, r%d, %d", rt, rs, imm);
   3347       ALUI_PATTERN(Iop_And32);
   3348       break;
   3349 
   3350    case 0x0E:     /* XORI */
   3351       DIP("xori r%d, r%d, %d", rt, rs, imm);
   3352       ALUI_PATTERN(Iop_Xor32);
   3353       break;
   3354 
   3355    case 0x0D:     /* ORI */
   3356       DIP("ori r%d, r%d, %d", rt, rs, imm);
   3357       ALUI_PATTERN(Iop_Or32);
   3358       break;
   3359 
   3360    case 0x0A:     /* SLTI */
   3361       DIP("slti r%d, r%d, %d", rt, rs, imm);
   3362       putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
   3363                                          mkU32(extend_s_16to32(imm)))));
   3364       break;
   3365 
   3366    case 0x0B:     /* SLTIU */
   3367       DIP("sltiu r%d, r%d, %d", rt, rs, imm);
   3368       putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
   3369                                          mkU32(extend_s_16to32(imm)))));
   3370       break;
   3371 
   3372    case 0x30:     /* LL / LWC0 */
   3373       DIP("ll r%d, %d(r%d)", rt, imm, rs);
   3374       LOAD_STORE_PATTERN;
   3375 
   3376       t2 = newTemp(Ity_I32);
   3377 #if defined (_MIPSEL)
   3378       stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /*this is a load */ ));
   3379 #elif defined (_MIPSEB)
   3380       stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /*this is a load */ ));
   3381 #endif
   3382 
   3383       putIReg(rt, mkexpr(t2));
   3384       break;
   3385 
   3386    case 0x38:     /* SC / SWC0 */
   3387       DIP("sc r%d, %d(r%d)", rt, imm, rs);
   3388       LOAD_STORE_PATTERN;
   3389 
   3390       t2 = newTemp(Ity_I1);
   3391 #if defined (_MIPSEL)
   3392       stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
   3393 #elif defined (_MIPSEB)
   3394       stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
   3395 #endif
   3396 
   3397       putIReg(rt, unop(Iop_1Uto32, mkexpr(t2)));
   3398       break;
   3399 
   3400  decode_failure:
   3401       /* All decode failures end up here. */
   3402       DIP("vex mips->IR: unhandled instruction bytes: "
   3403           "0x%x 0x%x 0x%x 0x%x\n",
   3404           (Int) getIByte(delta_start + 0),
   3405           (Int) getIByte(delta_start + 1),
   3406           (Int) getIByte(delta_start + 2),
   3407           (Int) getIByte(delta_start + 3));
   3408 
   3409       /* Tell the dispatcher that this insn cannot be decoded, and so has
   3410          not been executed, and (is currently) the next to be executed.
   3411          EIP should be up-to-date since it made so at the start bnezof each
   3412          insn, but nevertheless be paranoid and update it again right
   3413          now. */
   3414       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
   3415            mkU32(guest_PC_curr_instr)));
   3416       jmp_lit(&dres, Ijk_NoDecode, guest_PC_curr_instr);
   3417       dres.whatNext = Dis_StopHere;
   3418       dres.len = 0;
   3419       return dres;
   3420    }        /* switch (opc) for the main (primary) opcode switch. */
   3421 
   3422    /* All MIPS insn have 4 bytes */
   3423 
   3424    if (delay_slot_branch) {
   3425       delay_slot_branch = False;
   3426       stmt(bstmt);
   3427       bstmt = NULL;
   3428       putPC(mkU32(guest_PC_curr_instr + 4));
   3429       dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
   3430                          Ijk_Call : Ijk_Boring;
   3431    }
   3432 
   3433    if (likely_delay_slot) {
   3434       dres.jk_StopHere = Ijk_Boring;
   3435       dres.whatNext = Dis_StopHere;
   3436       putPC(lastn);
   3437       lastn = NULL;
   3438    }
   3439    if (delay_slot_jump) {
   3440       putPC(lastn);
   3441       lastn = NULL;
   3442       dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
   3443                          Ijk_Call : Ijk_Boring;
   3444    }
   3445 
   3446  decode_success:
   3447    /* All decode successes end up here. */
   3448    switch (dres.whatNext) {
   3449       case Dis_Continue:
   3450          putPC(mkU32(guest_PC_curr_instr + 4));
   3451          break;
   3452       case Dis_ResteerU:
   3453       case Dis_ResteerC:
   3454          putPC(mkU32(dres.continueAt));
   3455          break;
   3456       case Dis_StopHere:
   3457          break;
   3458       default:
   3459          vassert(0);
   3460          break;
   3461    }
   3462 
   3463    // On MIPS we need to check if the last instruction
   3464    // in block is branch or jump
   3465    if ((vex_control.guest_max_insns - 1) == (delta+4)/4)
   3466       if (branch_or_jump(guest_code + delta + 4)) {
   3467          dres.whatNext = Dis_StopHere;
   3468          dres.jk_StopHere = Ijk_Boring;
   3469          putPC(mkU32(guest_PC_curr_instr + 4));
   3470    }
   3471    dres.len = 4;
   3472 
   3473    DIP("\n");
   3474 
   3475    return dres;
   3476 
   3477 }
   3478 
   3479 /*------------------------------------------------------------*/
   3480 /*--- Top-level fn                                         ---*/
   3481 /*------------------------------------------------------------*/
   3482 
   3483 /* Disassemble a single instruction into IR.  The instruction
   3484    is located in host memory at &guest_code[delta]. */
   3485 
   3486 DisResult
   3487 disInstr_MIPS(IRSB*        irsb_IN,
   3488               Bool         (*resteerOkFn) (void *, Addr64),
   3489               Bool         resteerCisOk,
   3490               void*        callback_opaque,
   3491               UChar*       guest_code_IN,
   3492               Long         delta,
   3493               Addr64       guest_IP,
   3494               VexArch      guest_arch,
   3495               VexArchInfo* archinfo,
   3496               VexAbiInfo*  abiinfo,
   3497               Bool         host_bigendian_IN)
   3498 {
   3499    DisResult dres;
   3500 
   3501    /* Set globals (see top of this file) */
   3502    vassert(guest_arch == VexArchMIPS32);
   3503 
   3504    mode64 = guest_arch != VexArchMIPS32;
   3505 
   3506    guest_code = guest_code_IN;
   3507    irsb = irsb_IN;
   3508    host_is_bigendian = host_bigendian_IN;
   3509    guest_PC_curr_instr = (Addr32) guest_IP;
   3510    guest_PC_bbstart = (Addr32) toUInt(guest_IP - delta);
   3511 
   3512    dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque,
   3513                             delta, archinfo, abiinfo);
   3514 
   3515    return dres;
   3516 }
   3517 
   3518 /*--------------------------------------------------------------------*/
   3519 /*--- end                                        guest_mips_toIR.c ---*/
   3520 /*--------------------------------------------------------------------*/
   3521