Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                                   host_mips_isel.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., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 #include "libvex_basictypes.h"
     32 #include "libvex_ir.h"
     33 #include "libvex.h"
     34 
     35 #include "main_util.h"
     36 #include "main_globals.h"
     37 #include "host_generic_regs.h"
     38 #include "host_mips_defs.h"
     39 
     40 /*---------------------------------------------------------*/
     41 /*--- Register Usage Conventions                        ---*/
     42 /*---------------------------------------------------------*/
     43 /*
     44 
     45 Integer Regs
     46 ------------
     47 ZERO0       Reserved
     48 GPR1:9      Allocateable
     49 10          GuestStatePointer
     50 GPR1:9      Allocateable
     51 SP          StackFramePointer
     52 RA          LinkRegister
     53 
     54 */
     55 
     56 static Bool mode64 = False;
     57 
     58 /* GPR register class for mips32/64 */
     59 #define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
     60 
     61 /* FPR register class for mips32/64 */
     62 #define HRcFPR(__mode64) (__mode64 ? HRcFlt64 : HRcFlt32)
     63 
     64 /*---------------------------------------------------------*/
     65 /*--- ISelEnv                                           ---*/
     66 /*---------------------------------------------------------*/
     67 
     68 /* This carries around:
     69 
     70    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
     71      might encounter.  This is computed before insn selection starts,
     72      and does not change.
     73 
     74    - A mapping from IRTemp to HReg.  This tells the insn selector
     75      which virtual register(s) are associated with each IRTemp
     76      temporary.  This is computed before insn selection starts, and
     77      does not change.  We expect this mapping to map precisely the
     78      same set of IRTemps as the type mapping does.
     79 
     80         - vregmap   holds the primary register for the IRTemp.
     81         - vregmapHI is only used for 64-bit integer-typed
     82              IRTemps.  It holds the identity of a second
     83              32-bit virtual HReg, which holds the high half
     84              of the value.
     85 
     86    - The code array, that is, the insns selected so far.
     87 
     88    - A counter, for generating new virtual registers.
     89 
     90    - The host subarchitecture we are selecting insns for.
     91      This is set at the start and does not change.
     92 
     93    - A Bool for indicating whether we may generate chain-me
     94      instructions for control flow transfers, or whether we must use
     95      XAssisted.
     96 
     97    - The maximum guest address of any guest insn in this block.
     98      Actually, the address of the highest-addressed byte from any insn
     99      in this block.  Is set at the start and does not change.  This is
    100      used for detecting jumps which are definitely forward-edges from
    101      this block, and therefore can be made (chained) to the fast entry
    102      point of the destination, thereby avoiding the destination's
    103      event check.
    104 
    105    Note, this is all (well, mostly) host-independent.
    106 */
    107 
    108 typedef
    109    struct {
    110       /* Constant -- are set at the start and do not change. */
    111       IRTypeEnv*   type_env;
    112 
    113       HReg*        vregmap;
    114       HReg*        vregmapHI;
    115       Int          n_vregmap;
    116 
    117       UInt         hwcaps;
    118       Bool         mode64;
    119 
    120       Bool         chainingAllowed;
    121       Addr64       max_ga;
    122 
    123       /* These are modified as we go along. */
    124       HInstrArray* code;
    125       Int          vreg_ctr;
    126    }
    127    ISelEnv;
    128 
    129 static HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
    130 {
    131    vassert(tmp >= 0);
    132    vassert(tmp < env->n_vregmap);
    133    return env->vregmap[tmp];
    134 }
    135 
    136 static void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
    137 {
    138    vassert(tmp >= 0);
    139    vassert(tmp < env->n_vregmap);
    140    vassert(env->vregmapHI[tmp] != INVALID_HREG);
    141    *vrLO = env->vregmap[tmp];
    142    *vrHI = env->vregmapHI[tmp];
    143 }
    144 
    145 static void
    146 lookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
    147 {
    148    vassert(env->mode64);
    149    vassert(tmp >= 0);
    150    vassert(tmp < env->n_vregmap);
    151    vassert(env->vregmapHI[tmp] != INVALID_HREG);
    152    *vrLO = env->vregmap[tmp];
    153    *vrHI = env->vregmapHI[tmp];
    154 }
    155 
    156 static void addInstr(ISelEnv * env, MIPSInstr * instr)
    157 {
    158    addHInstr(env->code, instr);
    159    if (vex_traceflags & VEX_TRACE_VCODE) {
    160       ppMIPSInstr(instr, mode64);
    161       vex_printf("\n");
    162    }
    163 }
    164 
    165 static HReg newVRegI(ISelEnv * env)
    166 {
    167    HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
    168                      True /*virtual reg */ );
    169    env->vreg_ctr++;
    170    return reg;
    171 }
    172 
    173 static HReg newVRegD(ISelEnv * env)
    174 {
    175    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /*virtual reg */ );
    176    env->vreg_ctr++;
    177    return reg;
    178 }
    179 
    180 static HReg newVRegF(ISelEnv * env)
    181 {
    182    HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->mode64),
    183                      True /*virtual reg */ );
    184    env->vreg_ctr++;
    185    return reg;
    186 }
    187 
    188 static void add_to_sp(ISelEnv * env, UInt n)
    189 {
    190    HReg sp = StackPointer(mode64);
    191    vassert(n < 256 && (n % 8) == 0);
    192    addInstr(env, MIPSInstr_Alu(Malu_ADD, sp, sp, MIPSRH_Imm(True,
    193                                                             toUShort(n))));
    194 }
    195 
    196 static void sub_from_sp(ISelEnv * env, UInt n)
    197 {
    198    HReg sp = StackPointer(mode64);
    199    vassert(n < 256 && (n % 8) == 0);
    200    addInstr(env, MIPSInstr_Alu(Malu_SUB, sp, sp,
    201                                MIPSRH_Imm(True, toUShort(n))));
    202 }
    203 
    204 /*---------------------------------------------------------*/
    205 /*--- ISEL: Forward declarations                        ---*/
    206 /*---------------------------------------------------------*/
    207 
    208 /* These are organised as iselXXX and iselXXX_wrk pairs.  The
    209    iselXXX_wrk do the real work, but are not to be called directly.
    210    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
    211    checks that all returned registers are virtual.  You should not
    212    call the _wrk version directly.
    213 */
    214 /* 32-bit mode: Compute an I8/I16/I32 into a RH
    215                 (reg-or-halfword-immediate).
    216    It's important to specify whether the immediate is to be regarded
    217    as signed or not.  If yes, this will never return -32768 as an
    218    immediate; this guaranteed that all signed immediates that are
    219    return can have their sign inverted if need be.
    220 */
    221 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
    222 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
    223 
    224 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an immediate in
    225    the range 1 .. 31 inclusive.  Used for doing shift amounts. */
    226 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
    227 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
    228 
    229 /* compute an I8/I16/I32 into a GPR*/
    230 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e);
    231 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e);
    232 
    233 /* compute an I32 into an AMode. */
    234 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
    235                                          IRType xferTy);
    236 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy);
    237 
    238 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
    239                               IRExpr * e);
    240 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
    241 
    242 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
    243 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo,
    244                                ISelEnv * env, IRExpr * e);
    245 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
    246 
    247 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
    248 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
    249 
    250 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
    251 static HReg iselDblExpr(ISelEnv * env, IRExpr * e);
    252 
    253 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
    254 static HReg iselFltExpr(ISelEnv * env, IRExpr * e);
    255 
    256 static void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
    257 {
    258    /*
    259       rounding mode | MIPS | IR
    260       ------------------------
    261       to nearest    | 00  | 00
    262       to zero       | 01  | 11
    263       to +infinity  | 10  | 10
    264       to -infinity  | 11  | 01
    265     */
    266    // rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 2
    267    HReg irrm = iselWordExpr_R(env, mode);
    268    HReg tmp = newVRegI(env);
    269    HReg fcsr_old = newVRegI(env);
    270    MIPSAMode *am_addr;
    271 
    272    addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
    273                                 MIPSRH_Imm(False, 1)));
    274    addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
    275    addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp, MIPSRH_Imm(False, 3)));
    276    /* save old value of FCSR */
    277    addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
    278    sub_from_sp(env, 8); // Move SP down 4 bytes
    279    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
    280 
    281    //store old FCSR to stack
    282    addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
    283 
    284    //set new value of FCSR
    285    addInstr(env, MIPSInstr_MtFCSR(irrm));
    286 }
    287 
    288 static void set_MIPS_rounding_default(ISelEnv * env)
    289 {
    290    HReg fcsr = newVRegI(env);
    291    // load as float
    292    MIPSAMode *am_addr;
    293    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
    294 
    295    addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
    296 
    297    add_to_sp(env, 8);   // Reset SP
    298 
    299    //set new value of FCSR
    300    addInstr(env, MIPSInstr_MtFCSR(fcsr));
    301 }
    302 
    303 /*---------------------------------------------------------*/
    304 /*--- ISEL: Misc helpers                                ---*/
    305 /*---------------------------------------------------------*/
    306 
    307 /* Make an int reg-reg move. */
    308 static MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
    309 {
    310    vassert(hregClass(r_dst) == hregClass(r_src));
    311    vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
    312    return MIPSInstr_Alu(Malu_OR, r_dst, r_src, MIPSRH_Reg(r_src));
    313 }
    314 
    315 /*---------------------------------------------------------*/
    316 /*--- ISEL: Function call helpers                       ---*/
    317 /*---------------------------------------------------------*/
    318 
    319 /* Used only in doHelperCall.  See big comment in doHelperCall re
    320    handling of register-parameter args.  This function figures out
    321    whether evaluation of an expression might require use of a fixed
    322    register.  If in doubt return True (safe but suboptimal).
    323 */
    324 static Bool mightRequireFixedRegs(IRExpr * e)
    325 {
    326    switch (e->tag) {
    327       case Iex_RdTmp:
    328       case Iex_Const:
    329       case Iex_Get:
    330          return False;
    331       default:
    332          return True;
    333    }
    334 }
    335 
    336 /* Load 2*I32 regs to fp reg */
    337 static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
    338 {
    339    HReg fr_dst = newVRegD(env);
    340    MIPSAMode *am_addr0, *am_addr1;
    341 
    342    vassert(hregClass(r_srcHi) == HRcInt32);
    343    vassert(hregClass(r_srcLo) == HRcInt32);
    344 
    345    sub_from_sp(env, 16);   // Move SP down 16 bytes
    346    am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
    347    am_addr1 = MIPSAMode_IR(8, StackPointer(mode64));
    348 
    349    // store hi,lo as Ity_I32's
    350    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
    351    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
    352 
    353    // load as float
    354    addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
    355 
    356    add_to_sp(env, 16);  // Reset SP
    357    return fr_dst;
    358 }
    359 
    360 /* Do a complete function call.  guard is a Ity_Bit expression
    361    indicating whether or not the call happens.  If guard==NULL, the
    362    call is unconditional. */
    363 
    364 static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
    365                          IRCallee * cee, IRExpr ** args)
    366 {
    367    MIPSCondCode cc;
    368    HReg argregs[MIPS_N_REGPARMS];
    369    HReg tmpregs[MIPS_N_REGPARMS];
    370    Bool go_fast;
    371    Int n_args, i, argreg;
    372    UInt argiregs;
    373    ULong target;
    374    HReg src = 0;
    375 
    376    /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
    377       are allowed to be used for passing integer arguments. They correspond
    378       to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
    379       on MIPS host (since we only implement one calling convention) and so we
    380       always ignore it. */
    381 
    382    /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
    383       are allowed to be used for passing integer arguments. They correspond
    384       to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
    385       on MIPS host (since we only implement one calling convention) and so we
    386       always ignore it. */
    387    n_args = 0;
    388    for (i = 0; args[i]; i++)
    389       n_args++;
    390 
    391    if (MIPS_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {
    392       vpanic("doHelperCall(MIPS): cannot currently handle > 4 args");
    393    }
    394    argregs[0] = hregMIPS_GPR4(mode64);
    395    argregs[1] = hregMIPS_GPR5(mode64);
    396    argregs[2] = hregMIPS_GPR6(mode64);
    397    argregs[3] = hregMIPS_GPR7(mode64);
    398    argiregs = 0;
    399 
    400    tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
    401 
    402    /* First decide which scheme (slow or fast) is to be used.  First
    403       assume the fast scheme, and select slow if any contraindications
    404       (wow) appear. */
    405 
    406    go_fast = True;
    407 
    408    if (guard) {
    409       if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    410           && guard->Iex.Const.con->Ico.U1 == True) {
    411          /* unconditional */
    412       } else {
    413          /* Not manifestly unconditional -- be conservative. */
    414          go_fast = False;
    415       }
    416    }
    417 
    418    if (go_fast) {
    419       for (i = 0; i < n_args; i++) {
    420          if (mightRequireFixedRegs(args[i])) {
    421             go_fast = False;
    422             break;
    423          }
    424       }
    425    }
    426 
    427    /* save GuestStatePointer on the stack */
    428    sub_from_sp(env, 8);   // Move SP down 4 bytes
    429    addInstr(env, MIPSInstr_Store(4, MIPSAMode_IR(0, StackPointer(mode64)),
    430                                     GuestStatePointer(mode64), mode64));
    431 
    432    /* At this point the scheme to use has been established.  Generate
    433       code to get the arg values into the argument rregs. */
    434    if (go_fast) {
    435       /* FAST SCHEME */
    436       argreg = 0;
    437       if (passBBP) {
    438          argiregs |= (1 << (argreg + 4));
    439          addInstr(env, mk_iMOVds_RR(argregs[argreg],
    440                   GuestStatePointer(mode64)));
    441          argreg++;
    442       }
    443 
    444       for (i = 0; i < n_args; i++) {
    445          vassert(argreg < MIPS_N_REGPARMS);
    446          vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
    447                  || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
    448          if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
    449             argiregs |= (1 << (argreg + 4));
    450             addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
    451                      args[i])));
    452          } else { // Ity_I64
    453             vassert(mode64);
    454             argiregs |= (1 << (argreg + 4));
    455             addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
    456                      args[i])));
    457          }
    458          argreg++;
    459       }
    460       /* Fast scheme only applies for unconditional calls.  Hence: */
    461       cc = MIPScc_AL;
    462    } else {
    463       /* SLOW SCHEME; move via temporaries */
    464       argreg = 0;
    465       if (passBBP) {
    466          /* This is pretty stupid; better to move directly to r3
    467             after the rest of the args are done. */
    468          tmpregs[argreg] = newVRegI(env);
    469          addInstr(env, mk_iMOVds_RR(tmpregs[argreg],
    470                   GuestStatePointer(mode64)));
    471          argreg++;
    472       }
    473       for (i = 0; i < n_args; i++) {
    474          vassert(argreg < MIPS_N_REGPARMS);
    475          vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
    476                  || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
    477          if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
    478             tmpregs[argreg] = iselWordExpr_R(env, args[i]);
    479          } else { // Ity_I64
    480             vassert(mode64);
    481             tmpregs[argreg] = iselWordExpr_R(env, args[i]);
    482          }
    483          argreg++;
    484       }
    485 
    486       /* Now we can compute the condition.  We can't do it earlier
    487          because the argument computations could trash the condition
    488          codes.  Be a bit clever to handle the common case where the
    489          guard is 1:Bit. */
    490       cc = MIPScc_AL;
    491       if (guard) {
    492          if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    493              && guard->Iex.Const.con->Ico.U1 == True) {
    494             /* unconditional -- do nothing */
    495          } else {
    496             cc = iselCondCode(env, guard);
    497             src = iselWordExpr_R(env, guard);
    498          }
    499       }
    500       /* Move the args to their final destinations. */
    501       for (i = 0; i < argreg; i++) {
    502          if (tmpregs[i] == INVALID_HREG)  // Skip invalid regs
    503             continue;
    504          /* None of these insns, including any spill code that might
    505             be generated, may alter the condition codes. */
    506          argiregs |= (1 << (i + 4));
    507          addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
    508       }
    509    }
    510 
    511    target = toUInt(Ptr_to_ULong(cee->addr));
    512 
    513    /* Finally, the call itself. */
    514    if (mode64)
    515       if (cc == MIPScc_AL) {
    516          addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs));
    517       } else {
    518          addInstr(env, MIPSInstr_Call(cc, target, argiregs, src));
    519    } else if (cc == MIPScc_AL) {
    520       addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs));
    521    } else {
    522       addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src));
    523    }
    524    /* restore GuestStatePointer */
    525    addInstr(env, MIPSInstr_Load(4, GuestStatePointer(mode64),
    526             MIPSAMode_IR(0, StackPointer(mode64)), mode64));
    527    add_to_sp(env, 8);  // Reset SP
    528 }
    529 
    530 /*---------------------------------------------------------*/
    531 /*--- ISEL: Integer expression auxiliaries              ---*/
    532 /*---------------------------------------------------------*/
    533 
    534 /* --------------------- AMODEs --------------------- */
    535 
    536 /* Return an AMode which computes the value of the specified
    537    expression, possibly also adding insns to the code list as a
    538    result.  The expression may only be a word-size one.
    539 */
    540 
    541 static Bool uInt_fits_in_16_bits(UInt u)
    542 {
    543    Int i = u & 0xFFFF;
    544    i <<= 16;
    545    i >>= 16;
    546    return toBool(u == (UInt) i);
    547 }
    548 
    549 static Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
    550 {
    551    switch (am->tag) {
    552       case Mam_IR:
    553          return toBool(hregClass(am->Mam.IR.base) == HRcGPR(mode64) &&
    554                   hregIsVirtual(am->Mam.IR.base) &&
    555                   uInt_fits_in_16_bits(am->Mam.IR.index));
    556       case Mam_RR:
    557          return toBool(hregClass(am->Mam.RR.base) == HRcGPR(mode64) &&
    558                   hregIsVirtual(am->Mam.RR.base) &&
    559                   hregClass(am->Mam.RR.index) == HRcGPR(mode64) &&
    560                   hregIsVirtual(am->Mam.IR.index));
    561       default:
    562          vpanic("sane_AMode: unknown mips amode tag");
    563    }
    564 }
    565 
    566 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
    567 {
    568    MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
    569    vassert(sane_AMode(env, am));
    570    return am;
    571 }
    572 
    573 /* DO NOT CALL THIS DIRECTLY ! */
    574 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
    575                 IRType xferTy)
    576 {
    577    IRType ty = typeOfIRExpr(env->type_env, e);
    578    {
    579       vassert(ty == Ity_I32);
    580 
    581       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
    582       if (e->tag == Iex_Binop
    583           && e->Iex.Binop.op == Iop_Add32
    584           && e->Iex.Binop.arg2->tag == Iex_Const
    585           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
    586           && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con-> Ico.U32)) {
    587          return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
    588                               iselWordExpr_R(env, e->Iex.Binop.arg1));
    589       }
    590 
    591       /* Add32(expr,expr) */
    592       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) {
    593          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
    594          HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
    595 
    596          return MIPSAMode_RR(r_idx, r_base);
    597       }
    598    }
    599 
    600    /* Doesn't match anything in particular.  Generate it into
    601       a register and use that. */
    602    return MIPSAMode_IR(0, iselWordExpr_R(env, e));
    603 }
    604 
    605 /*---------------------------------------------------------*/
    606 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
    607 /*---------------------------------------------------------*/
    608 
    609 /* Select insns for an integer-typed expression, and add them to the
    610    code list.  Return a reg holding the result.  This reg will be a
    611    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
    612    want to modify it, ask for a new vreg, copy it in there, and modify
    613    the copy.  The register allocator will do its best to map both
    614    vregs to the same real register, so the copies will often disappear
    615    later in the game.
    616 
    617    This should handle expressions of 64, 32, 16 and 8-bit type.
    618    All results are returned in a (mode64 ? 64bit : 32bit) register.
    619    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
    620    are arbitrary, so you should mask or sign extend partial values
    621    if necessary.
    622 */
    623 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
    624 {
    625    HReg r = iselWordExpr_R_wrk(env, e);
    626    /* sanity checks ... */
    627 
    628    vassert(hregClass(r) == HRcGPR(env->mode64));
    629    vassert(hregIsVirtual(r));
    630    return r;
    631 }
    632 
    633 /* DO NOT CALL THIS DIRECTLY ! */
    634 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
    635 {
    636    IRType ty = typeOfIRExpr(env->type_env, e);
    637    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1
    638            || ty == Ity_F32 || (ty == Ity_I64 && mode64)
    639            || (ty == Ity_I128 && mode64));
    640 
    641    switch (e->tag) {
    642       /* --------- TEMP --------- */
    643       case Iex_RdTmp:
    644          return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    645 
    646       /* --------- LOAD --------- */
    647       case Iex_Load: {
    648          HReg r_dst = newVRegI(env);
    649          MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
    650 
    651          if (e->Iex.Load.end != Iend_LE
    652              && e->Iex.Load.end != Iend_BE)
    653             goto irreducible;
    654 
    655          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
    656                                       r_dst, am_addr, mode64));
    657          return r_dst;
    658       }
    659 
    660       /* --------- BINARY OP --------- */
    661       case Iex_Binop: {
    662          MIPSAluOp aluOp;
    663          MIPSShftOp shftOp;
    664 
    665          /* Is it an addition or logical style op? */
    666          switch (e->Iex.Binop.op) {
    667             case Iop_Add32:
    668                aluOp = Malu_ADD;
    669                break;
    670 
    671             case Iop_Sub8:
    672             case Iop_Sub16:
    673             case Iop_Sub32:
    674                aluOp = Malu_SUB;
    675                break;
    676 
    677             case Iop_And32:
    678             case Iop_And64:
    679                aluOp = Malu_AND;
    680                break;
    681 
    682             case Iop_Or32:
    683             case Iop_Or64:
    684                aluOp = Malu_OR;
    685                break;
    686 
    687             case Iop_Xor32:
    688             case Iop_Xor64:
    689                aluOp = Malu_XOR;
    690                break;
    691 
    692             default:
    693                aluOp = Malu_INVALID;
    694                break;
    695          }
    696 
    697          /* For commutative ops we assume any literal
    698             values are on the second operand. */
    699          if (aluOp != Malu_INVALID) {
    700             HReg r_dst = newVRegI(env);
    701             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    702             MIPSRH *ri_srcR = NULL;
    703             /* get right arg into an RH, in the appropriate way */
    704             switch (aluOp) {
    705                case Malu_ADD:
    706                case Malu_SUB:
    707                   ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
    708                                             e->Iex.Binop.arg2);
    709                   break;
    710                case Malu_AND:
    711                case Malu_OR:
    712                case Malu_XOR:
    713                   ri_srcR = iselWordExpr_RH(env, False /*unsigned */,
    714                                             e->Iex.Binop.arg2);
    715                   break;
    716                default:
    717                   vpanic("iselWordExpr_R_wrk-aluOp-arg2");
    718             }
    719             addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
    720             return r_dst;
    721          }
    722 
    723          /* a shift? */
    724          switch (e->Iex.Binop.op) {
    725             case Iop_Shl32:
    726             case Iop_Shl64:
    727                shftOp = Mshft_SLL;
    728                break;
    729             case Iop_Shr32:
    730             case Iop_Shr64:
    731                shftOp = Mshft_SRL;
    732                break;
    733             case Iop_Sar32:
    734             case Iop_Sar64:
    735                shftOp = Mshft_SRA;
    736                break;
    737             default:
    738                shftOp = Mshft_INVALID;
    739                break;
    740          }
    741 
    742          /* we assume any literal values are on the second operand. */
    743          if (shftOp != Mshft_INVALID) {
    744             HReg r_dst = newVRegI(env);
    745             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    746             MIPSRH *ri_srcR = NULL;
    747             /* get right arg into an RH, in the appropriate way */
    748             switch (shftOp) {
    749                case Mshft_SLL:
    750                case Mshft_SRL:
    751                case Mshft_SRA:
    752                   ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop. arg2);
    753                   break;
    754                default:
    755                   vpanic("iselIntExpr_R_wrk-shftOp-arg2");
    756             }
    757             /* widen the left arg if needed */
    758             /*TODO do we need this? */
    759             if (ty == Ity_I8 || ty == Ity_I16)
    760                goto irreducible;
    761             if (ty == Ity_I64) {
    762                vassert(mode64);
    763                addInstr(env, MIPSInstr_Shft(shftOp, False/*64bit shift */,
    764                                             r_dst, r_srcL, ri_srcR));
    765             } else {
    766                addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
    767                                             r_dst, r_srcL, ri_srcR));
    768             }
    769             return r_dst;
    770          }
    771 
    772          /* Cmp*32*(x,y) ? */
    773          if (e->Iex.Binop.op == Iop_CmpEQ32
    774              || e->Iex.Binop.op == Iop_CmpNE32
    775              || e->Iex.Binop.op == Iop_CmpNE64
    776              || e->Iex.Binop.op == Iop_CmpLT32S
    777              || e->Iex.Binop.op == Iop_CmpLT32U
    778              || e->Iex.Binop.op == Iop_CmpLT64U
    779              || e->Iex.Binop.op == Iop_CmpLE32S
    780              || e->Iex.Binop.op == Iop_CmpLE64S
    781              || e->Iex.Binop.op == Iop_CmpLT64S
    782              || e->Iex.Binop.op == Iop_CmpEQ64) {
    783 
    784             Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
    785                          || e->Iex.Binop.op == Iop_CmpLE32S
    786                          || e->Iex.Binop.op == Iop_CmpLT64S
    787                          || e->Iex.Binop.op == Iop_CmpLE64S);
    788             Bool size32;
    789             HReg dst = newVRegI(env);
    790             HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
    791             HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
    792 
    793             MIPSCondCode cc;
    794 
    795             switch (e->Iex.Binop.op) {
    796                case Iop_CmpEQ32:
    797                   cc = MIPScc_EQ;
    798                   size32 = True;
    799                   break;
    800                case Iop_CmpNE32:
    801                   cc = MIPScc_NE;
    802                   size32 = True;
    803                   break;
    804                case Iop_CmpNE64:
    805                   cc = MIPScc_NE;
    806                   size32 = True;
    807                   break;
    808                case Iop_CmpLT32S:
    809                   cc = MIPScc_LT;
    810                   size32 = True;
    811                   break;
    812                case Iop_CmpLT32U:
    813                   cc = MIPScc_LO;
    814                   size32 = True;
    815                   break;
    816                case Iop_CmpLT64U:
    817                   cc = MIPScc_LO;
    818                   size32 = False;
    819                   break;
    820                case Iop_CmpLE32S:
    821                   cc = MIPScc_LE;
    822                   size32 = True;
    823                   break;
    824                case Iop_CmpLE64S:
    825                   cc = MIPScc_LE;
    826                   size32 = False;
    827                   break;
    828                case Iop_CmpLT64S:
    829                   cc = MIPScc_LT;
    830                   size32 = False;
    831                   break;
    832                case Iop_CmpEQ64:
    833                   cc = MIPScc_EQ;
    834                   size32 = False;
    835                   break;
    836                default:
    837                   vpanic
    838                       ("iselCondCode(mips): CmpXX32 or CmpXX64");
    839             }
    840 
    841             addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
    842             return dst;
    843          }
    844 
    845          if (e->Iex.Binop.op == Iop_Max32U) {
    846             /*
    847                tmp = argR - argL;
    848                dst = argL;
    849                bltz tmp,2;
    850                dst = argR;
    851 
    852              */
    853             HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    854             MIPSRH *argR = iselWordExpr_RH(env, False /*signed */ ,
    855                                            e->Iex.Binop.arg2);
    856             HReg dst = newVRegI(env);
    857             HReg tmp = newVRegI(env);
    858             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, argL, argR));
    859             addInstr(env, MIPSInstr_MovCond(dst, argL, argR, tmp, MIPScc_MI));
    860 
    861             return dst;
    862          }
    863 
    864          if (e->Iex.Binop.op == Iop_Mul32 || e->Iex.Binop.op == Iop_Mul64) {
    865             Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
    866             HReg r_dst = newVRegI(env);
    867             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    868             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
    869             addInstr(env, MIPSInstr_Mul(False/*Unsigned or Signed */ ,
    870                                        False /*widen */ ,
    871                                        sz32 /*32bit or 64bit */,
    872                                        r_dst, r_srcL, r_srcR));
    873             return r_dst;
    874          }
    875 
    876          if (e->Iex.Binop.op == Iop_MullU32 || e->Iex.Binop.op == Iop_MullS32) {
    877             HReg r_dst = newVRegI(env);
    878             HReg tHi = newVRegI(env);
    879             HReg tLo = newVRegI(env);
    880             HReg tLo_1 = newVRegI(env);
    881             HReg tHi_1 = newVRegI(env);
    882             HReg mask = newVRegI(env);
    883 
    884             Bool syned = toBool(e->Iex.Binop.op == Iop_MullS32);
    885             Bool size = toBool(e->Iex.Binop.op == Iop_MullS32)
    886                         || toBool(e->Iex.Binop.op == Iop_MullU32);
    887             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    888             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
    889             addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */ ,
    890                                         True /*widen */ ,
    891                                         size /*32bit or 64bit mul */ ,
    892                                         r_dst, r_srcL, r_srcR));
    893 
    894             addInstr(env, MIPSInstr_Mfhi(tHi));
    895             addInstr(env, MIPSInstr_Mflo(tLo));
    896 
    897             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1,
    898                           tHi, MIPSRH_Imm(False, 32)));
    899 
    900             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
    901             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
    902                           MIPSRH_Reg(mask)));
    903 
    904             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
    905                           MIPSRH_Reg(tLo_1)));
    906 
    907             return r_dst;
    908          }
    909 
    910          if (e->Iex.Binop.op == Iop_CmpF64) {
    911             HReg r_srcL, r_srcR;
    912             {
    913                r_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
    914                r_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
    915             }
    916             HReg tmp = newVRegI(env);
    917             HReg r_ccMIPS = newVRegI(env);
    918             HReg r_ccIR = newVRegI(env);
    919             HReg r_ccIR_b0 = newVRegI(env);
    920             HReg r_ccIR_b2 = newVRegI(env);
    921             HReg r_ccIR_b6 = newVRegI(env);
    922 
    923             /* Create in dst, the IRCmpF64Result encoded result. */
    924             // chech for EQ
    925             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
    926                                               toUChar(2)));
    927             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_ccMIPS, tmp,
    928                                          MIPSRH_Imm(False, 22)));
    929             // chech for UN
    930             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
    931                                               toUChar(1)));
    932             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
    933                                         MIPSRH_Imm(False, 23)));
    934             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
    935                                         MIPSRH_Reg(tmp)));
    936             // chech for LT
    937             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
    938                                               toUChar(12)));
    939             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp,
    940                                          tmp, MIPSRH_Imm(False, 21)));
    941             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
    942                                         MIPSRH_Reg(tmp)));
    943             // chech for GT
    944             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
    945                                               toUChar(15)));
    946             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
    947                                          MIPSRH_Imm(False, 20)));
    948 
    949             addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
    950             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
    951                                         MIPSRH_Imm(False, 8)));
    952             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
    953                                         MIPSRH_Reg(tmp)));
    954             /* Map compare result from PPC to IR,
    955                conforming to CmpF64 definition. */
    956             /*
    957                FP cmp result | MIPS | IR
    958                --------------------------
    959                UN            | 0x1 | 0x45
    960                EQ            | 0x2 | 0x40
    961                GT            | 0x4 | 0x00
    962                LT            | 0x8 | 0x01
    963              */
    964 
    965             // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
    966             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b0, r_ccMIPS,
    967                           MIPSRH_Imm(False, 0x3)));
    968             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b0, r_ccMIPS,
    969                           MIPSRH_Reg(r_ccIR_b0)));
    970             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b0, r_ccIR_b0,
    971                           MIPSRH_Imm(False, 0x1)));
    972 
    973             // r_ccIR_b2 = r_ccPPC[0]
    974             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b2, r_ccMIPS,
    975                           MIPSRH_Imm(False, 0x2)));
    976             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b2, r_ccIR_b2,
    977                           MIPSRH_Imm(False, 0x4)));
    978 
    979             // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
    980             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b6,
    981                           r_ccMIPS, MIPSRH_Imm(False, 0x1)));
    982             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b6, r_ccMIPS,
    983                           MIPSRH_Reg(r_ccIR_b6)));
    984             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b6, r_ccIR_b6,
    985                           MIPSRH_Imm(False, 0x6)));
    986             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b6, r_ccIR_b6,
    987                           MIPSRH_Imm(False, 0x40)));
    988 
    989             // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
    990             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR_b0,
    991                           MIPSRH_Reg(r_ccIR_b2)));
    992             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR,
    993                           MIPSRH_Reg(r_ccIR_b6)));
    994             return r_ccIR;
    995          }
    996 
    997          if (e->Iex.Binop.op == Iop_DivModU64to32 ||
    998              e->Iex.Binop.op == Iop_DivModS64to32) {
    999             HReg tLo = newVRegI(env);
   1000             HReg tHi = newVRegI(env);
   1001             HReg mask = newVRegI(env);
   1002             HReg tLo_1 = newVRegI(env);
   1003             HReg tHi_1 = newVRegI(env);
   1004             HReg r_dst = newVRegI(env);
   1005             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
   1006 
   1007             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1008             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1009 
   1010             addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
   1011             addInstr(env, MIPSInstr_Mfhi(tHi));
   1012             addInstr(env, MIPSInstr_Mflo(tLo));
   1013 
   1014             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
   1015                                          MIPSRH_Imm(False, 32)));
   1016 
   1017             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
   1018             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1019                           MIPSRH_Reg(mask)));
   1020 
   1021             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1022                           MIPSRH_Reg(tLo_1)));
   1023 
   1024             return r_dst;
   1025          }
   1026 
   1027          if (e->Iex.Binop.op == Iop_32HLto64) {
   1028             vassert(mode64);
   1029             HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1030             HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1031             HReg tLo_1 = newVRegI(env);
   1032             HReg tHi_1 = newVRegI(env);
   1033             HReg r_dst = newVRegI(env);
   1034             HReg mask = newVRegI(env);
   1035 
   1036             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
   1037                                          MIPSRH_Imm(False, 32)));
   1038 
   1039             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
   1040             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1041                           MIPSRH_Reg(mask)));
   1042             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1043                           MIPSRH_Reg(tLo_1)));
   1044 
   1045             return r_dst;
   1046          }
   1047 
   1048          if (e->Iex.Binop.op == Iop_F64toI32S) {
   1049             HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
   1050             HReg valS = newVRegF(env);
   1051             HReg r_dst = newVRegI(env);
   1052             MIPSAMode *am_addr;
   1053 
   1054             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   1055             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
   1056             set_MIPS_rounding_default(env);
   1057 
   1058             sub_from_sp(env, 16);   // Move SP down 16 bytes
   1059             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   1060 
   1061             // store as F32
   1062             addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 4, valS, am_addr));
   1063             // load as I32
   1064             addInstr(env, MIPSInstr_Load(4, r_dst, am_addr, mode64));
   1065 
   1066             add_to_sp(env, 16);  // Reset SP
   1067 
   1068             return r_dst;
   1069          }
   1070 
   1071       break;
   1072    }
   1073 
   1074       /* --------- UNARY OP --------- */
   1075    case Iex_Unop: {
   1076       IROp op_unop = e->Iex.Unop.op;
   1077 
   1078       switch (op_unop) {
   1079          case Iop_1Sto32:
   1080          case Iop_8Sto32:
   1081          case Iop_16Sto32:
   1082          case Iop_16Sto64:
   1083          case Iop_8Sto64:
   1084          case Iop_1Sto64: {
   1085             HReg r_dst = newVRegI(env);
   1086             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1087             Bool sz32;
   1088             UShort amt;
   1089             switch (op_unop) {
   1090                case Iop_1Sto32:
   1091                   amt = 31;
   1092                   sz32 = True;
   1093                   break;
   1094                case Iop_16Sto32:
   1095                   amt = 16;
   1096                   sz32 = True;
   1097                   break;
   1098                case Iop_16Sto64:
   1099                   amt = 48;
   1100                   sz32 = False;
   1101                   break;
   1102                case Iop_8Sto32:
   1103                   amt = 24;
   1104                   sz32 = True;
   1105                   break;
   1106                case Iop_8Sto64:
   1107                   amt = 56;
   1108                   sz32 = False;
   1109                   break;
   1110                case Iop_1Sto64:
   1111                   amt = 63;
   1112                   sz32 = False;
   1113                   break;
   1114                default:
   1115                   vassert(0);
   1116             }
   1117 
   1118             addInstr(env, MIPSInstr_Shft(Mshft_SLL, sz32, r_dst, r_src,
   1119                                          MIPSRH_Imm(False, amt)));
   1120             addInstr(env, MIPSInstr_Shft(Mshft_SRA, sz32, r_dst, r_dst,
   1121                                          MIPSRH_Imm(False, amt)));
   1122             return r_dst;
   1123          }
   1124 
   1125          /*not(x) = nor(x,x) */
   1126          case Iop_Not1: {
   1127             HReg r_dst = newVRegI(env);
   1128             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1129             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   1130 
   1131             addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   1132             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
   1133             return r_dst;
   1134          }
   1135 
   1136          case Iop_Not32:
   1137          case Iop_Not64: {
   1138             HReg r_dst = newVRegI(env);
   1139             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1140             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   1141 
   1142             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
   1143             return r_dst;
   1144          }
   1145 
   1146          case Iop_ReinterpF32asI32: {
   1147             MIPSAMode *am_addr;
   1148             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
   1149             HReg r_dst = newVRegI(env);
   1150 
   1151             sub_from_sp(env, 16);   // Move SP down 16 bytes
   1152             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   1153 
   1154             // store as F32
   1155             addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 4, fr_src,
   1156                                            am_addr));
   1157             // load as Ity_I32
   1158             addInstr(env, MIPSInstr_Load(4, r_dst, am_addr, mode64));
   1159 
   1160             add_to_sp(env, 16);  // Reset SP
   1161             return r_dst;
   1162          }
   1163 
   1164          case Iop_ReinterpF64asI64: {
   1165             vassert(mode64);
   1166             MIPSAMode *am_addr;
   1167             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
   1168             HReg r_dst = newVRegI(env);
   1169 
   1170             sub_from_sp(env, 16);   // Move SP down 16 bytes
   1171             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   1172 
   1173             // store as F64
   1174             addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 8, fr_src,
   1175                                            am_addr));
   1176             // load as Ity_I64
   1177             addInstr(env, MIPSInstr_Load(8, r_dst, am_addr, mode64));
   1178 
   1179             add_to_sp(env, 16);  // Reset SP
   1180             return r_dst;
   1181          }
   1182 
   1183          case Iop_32to8:
   1184          case Iop_32to16:
   1185             return iselWordExpr_R(env, e->Iex.Unop.arg);
   1186 
   1187          case Iop_64to8: {
   1188             vassert(mode64);
   1189             HReg r_src, r_dst;
   1190             r_dst = newVRegI(env);
   1191             r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1192             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
   1193                           MIPSRH_Imm(False, 0xFF)));
   1194             return r_dst;
   1195          }
   1196 
   1197          case Iop_16Uto32:
   1198          case Iop_8Uto32:
   1199          case Iop_1Uto32: {
   1200             HReg r_dst = newVRegI(env);
   1201             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1202             UShort amt;
   1203             switch (op_unop) {
   1204                case Iop_1Uto32:
   1205                case Iop_1Uto8:
   1206                   amt = 31;
   1207                   break;
   1208 
   1209                case Iop_16Uto32:
   1210                   amt = 16;
   1211                   break;
   1212 
   1213                default:
   1214                   amt = 24;
   1215                   break;
   1216             }
   1217 
   1218             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_dst, r_src,
   1219                           MIPSRH_Imm(False, amt)));
   1220             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_dst, r_dst,
   1221                           MIPSRH_Imm(False, amt)));
   1222             return r_dst;
   1223          }
   1224 
   1225          case Iop_8Uto16:
   1226          case Iop_8Uto64:
   1227          case Iop_16Uto64: {
   1228             vassert(mode64);
   1229             HReg r_dst = newVRegI(env);
   1230             HReg r_src = iselWordExpr_R(env,  e->Iex.Unop.arg);
   1231             UShort mask = toUShort(op_unop == Iop_16Uto64 ? 0xFFFF :
   1232                                    op_unop == Iop_16Uto32 ? 0xFFFF : 0xFF);
   1233             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
   1234                           MIPSRH_Imm(False, mask)));
   1235             return r_dst;
   1236          }
   1237 
   1238          case Iop_32Uto64: {
   1239             HReg r_dst = newVRegI(env);
   1240             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1241             vassert(mode64);
   1242             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False/*!32bit shift */,
   1243                                          r_dst, r_src, MIPSRH_Imm(False, 32)));
   1244             addInstr(env, MIPSInstr_Shft(Mshft_SRL, False/*!32bit shift */,
   1245                                          r_dst, r_dst, MIPSRH_Imm(False, 32)));
   1246             return r_dst;
   1247          }
   1248 
   1249          case Iop_1Uto64:
   1250             vassert(mode64);
   1251             return iselWordExpr_R(env, e->Iex.Unop.arg);
   1252 
   1253          case Iop_64HIto32: {
   1254             HReg rHi, rLo;
   1255             iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1256             return rHi;
   1257          }
   1258 
   1259          case Iop_64to32: {
   1260             HReg rHi, rLo;
   1261             iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1262             return rLo;
   1263          }
   1264 
   1265          case Iop_64to16: {
   1266             vassert(env->mode64);
   1267             HReg r_dst = newVRegI(env);
   1268             r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
   1269             return r_dst;
   1270          }
   1271 
   1272          case Iop_32Sto64: {
   1273             HReg r_dst = newVRegI(env);
   1274             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1275             vassert(mode64);
   1276             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True/*!32bit shift */,
   1277                                          r_dst, r_src, MIPSRH_Imm(True, 0)));
   1278             return r_dst;
   1279          }
   1280 
   1281          case Iop_CmpNEZ8: {
   1282             HReg r_dst = newVRegI(env);
   1283             HReg tmp = newVRegI(env);
   1284             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1285 
   1286             MIPSCondCode cc;
   1287 
   1288             cc = MIPScc_NE;
   1289             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
   1290                                         MIPSRH_Imm(False, 0xFF)));
   1291             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
   1292                                         hregMIPS_GPR0(mode64), cc));
   1293             return r_dst;
   1294          }
   1295 
   1296          case Iop_CmpNEZ32: {
   1297             HReg r_dst = newVRegI(env);
   1298             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1299 
   1300             MIPSCondCode cc;
   1301 
   1302             cc = MIPScc_NE;
   1303 
   1304             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
   1305                                         hregMIPS_GPR0(mode64), cc));
   1306             return r_dst;
   1307          }
   1308 
   1309          case Iop_CmpwNEZ32: {
   1310             HReg r_dst = newVRegI(env);
   1311             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1312 
   1313             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
   1314                           MIPSRH_Reg(r_src)));
   1315 
   1316             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
   1317                                         MIPSRH_Reg(r_src)));
   1318             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
   1319                                          MIPSRH_Imm(False, 31)));
   1320             return r_dst;
   1321          }
   1322 
   1323          case Iop_Left8:
   1324          case Iop_Left32:
   1325          case Iop_Left64: {
   1326             if (op_unop == Iop_Left64 && !mode64)
   1327                goto irreducible;
   1328             HReg r_dst = newVRegI(env);
   1329             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1330             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
   1331                           MIPSRH_Reg(r_src)));
   1332             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
   1333                           MIPSRH_Reg(r_src)));
   1334             return r_dst;
   1335          }
   1336 
   1337          case Iop_Clz32: {
   1338             HReg r_dst = newVRegI(env);
   1339             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1340             addInstr(env, MIPSInstr_Unary(Mun_CLZ, r_dst, r_src));
   1341             return r_dst;
   1342          }
   1343 
   1344          case Iop_CmpNEZ64: {
   1345             HReg hi, lo;
   1346             HReg r_dst = newVRegI(env);
   1347             HReg r_src;
   1348             r_src = newVRegI(env);
   1349             iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
   1350             addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
   1351             MIPSCondCode cc;
   1352 
   1353             cc = MIPScc_NE;
   1354 
   1355             addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
   1356                                         hregMIPS_GPR0(mode64), cc));
   1357             return r_dst;
   1358          }
   1359 
   1360          case Iop_CmpwNEZ64: {
   1361             HReg tmp1;
   1362             HReg tmp2 = newVRegI(env);
   1363             vassert(env->mode64);
   1364             tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
   1365 
   1366             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
   1367                           MIPSRH_Reg(tmp1)));
   1368 
   1369             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
   1370             addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
   1371                                          MIPSRH_Imm (False, 63)));
   1372             return tmp2;
   1373          }
   1374 
   1375          case Iop_128HIto64: {
   1376             vassert(mode64);
   1377             HReg rHi, rLo;
   1378             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1379             return rHi; /* and abandon rLo .. poor wee thing :-) */
   1380          }
   1381 
   1382          case Iop_128to64: {
   1383             vassert(mode64);
   1384             HReg rHi, rLo;
   1385             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1386             return rLo; /* and abandon rLo .. poor wee thing :-) */
   1387          }
   1388 
   1389          default:
   1390             break;
   1391       }
   1392       break;
   1393    }
   1394 
   1395       /* --------- GET --------- */
   1396    case Iex_Get: {
   1397       if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
   1398           || ((ty == Ity_I64) && mode64)) {
   1399          HReg r_dst = newVRegI(env);
   1400 
   1401          MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   1402                                            GuestStatePointer(mode64));
   1403          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
   1404                                       mode64));
   1405          return r_dst;
   1406       }
   1407       break;
   1408    }
   1409 
   1410       /* --------- MULTIPLEX --------- */
   1411    case Iex_Mux0X: {
   1412       if ((ty == Ity_I8 || ty == Ity_I16 ||
   1413            ty == Ity_I32 || ((ty == Ity_I64))) &&
   1414            typeOfIRExpr(env->type_env, e->Iex.Mux0X.cond) == Ity_I8) {
   1415          /*
   1416           * r_dst = cond && rX
   1417           * cond = not(cond)
   1418           * tmp = cond && r0
   1419           * r_dst = tmp + r_dst
   1420           */
   1421          HReg r0 = iselWordExpr_R(env, e->Iex.Mux0X.expr0);
   1422          HReg rX = iselWordExpr_R(env, e->Iex.Mux0X.exprX);
   1423          HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
   1424          HReg r_dst = newVRegI(env);
   1425          HReg r_tmp = newVRegI(env);
   1426          HReg r_tmp1 = newVRegI(env);
   1427          HReg r_cond_neg = newVRegI(env);
   1428 
   1429          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp, r_cond, MIPSRH_Reg(rX)));
   1430          addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
   1431                        MIPSRH_Reg(r_cond)));
   1432          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1, r_cond_neg,
   1433                        MIPSRH_Reg(r0)));
   1434          addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst, r_tmp,
   1435                        MIPSRH_Reg(r_tmp1)));
   1436 
   1437          return r_dst;
   1438       }
   1439       break;
   1440    }
   1441 
   1442       /* --------- LITERAL --------- */
   1443       /* 32/16/8-bit literals */
   1444    case Iex_Const: {
   1445       Long l;
   1446       HReg r_dst = newVRegI(env);
   1447       IRConst *con = e->Iex.Const.con;
   1448       switch (con->tag) {
   1449          case Ico_U64:
   1450             if (!mode64)
   1451                goto irreducible;
   1452             l = (Long) con->Ico.U64;
   1453             break;
   1454          case Ico_U32:
   1455             l = (Long) (Int) con->Ico.U32;
   1456             break;
   1457          case Ico_U16:
   1458             l = (Long) (Int) (Short) con->Ico.U16;
   1459             break;
   1460          case Ico_U8:
   1461             l = (Long) (Int) (Char) con->Ico.U8;
   1462             break;
   1463          default:
   1464             vpanic("iselIntExpr_R.const(mips)");
   1465       }
   1466       addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
   1467       return r_dst;
   1468    }
   1469 
   1470       /* --------- CCALL --------- */
   1471    case Iex_CCall: {
   1472       HReg r_dst = newVRegI(env);
   1473       vassert(ty == e->Iex.CCall.retty);
   1474 
   1475       /* be very restrictive for now.  Only 32/64-bit ints allowed
   1476          for args, and 32 bits for return type. */
   1477       if (e->Iex.CCall.retty != Ity_I32 && !mode64)
   1478          goto irreducible;
   1479 
   1480       /* Marshal args, do the call, clear stack. */
   1481       doHelperCall(env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args);
   1482       addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
   1483       return r_dst;
   1484    }
   1485 
   1486    default:
   1487       break;
   1488    }        /* end switch(e->tag) */
   1489 
   1490    /* We get here if no pattern matched. */
   1491    irreducible:
   1492       vex_printf("--------------->\n");
   1493       if (e->tag == Iex_RdTmp)
   1494          vex_printf("Iex_RdTmp \n");
   1495       ppIRExpr(e);
   1496 
   1497       vpanic("iselWordExpr_R(mips): cannot reduce tree");
   1498 }
   1499 
   1500 /* --------------------- RH --------------------- */
   1501 
   1502 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
   1503    (reg-or-halfword-immediate).  It's important to specify whether the
   1504    immediate is to be regarded as signed or not.  If yes, this will
   1505    never return -32768 as an immediate; this guaranteed that all
   1506    signed immediates that are return can have their sign inverted if
   1507    need be. */
   1508 
   1509 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
   1510 {
   1511    MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
   1512    /* sanity checks ... */
   1513    switch (ri->tag) {
   1514       case Mrh_Imm:
   1515          vassert(ri->Mrh.Imm.syned == syned);
   1516          if (syned)
   1517             vassert(ri->Mrh.Imm.imm16 != 0x8000);
   1518          return ri;
   1519       case Mrh_Reg:
   1520          vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
   1521          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
   1522          return ri;
   1523       default:
   1524          vpanic("iselIntExpr_RH: unknown mips RH tag");
   1525    }
   1526 }
   1527 
   1528 /* DO NOT CALL THIS DIRECTLY ! */
   1529 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
   1530 {
   1531    ULong u;
   1532    Long l;
   1533    IRType ty = typeOfIRExpr(env->type_env, e);
   1534    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1535           ((ty == Ity_I64) && env->mode64));
   1536 
   1537    /* special case: immediate */
   1538    if (e->tag == Iex_Const) {
   1539       IRConst *con = e->Iex.Const.con;
   1540       /* What value are we aiming to generate? */
   1541       switch (con->tag) {
   1542          /* Note: Not sign-extending - we carry 'syned' around */
   1543          case Ico_U64:
   1544             vassert(env->mode64);
   1545             u = con->Ico.U64;
   1546             break;
   1547          case Ico_U32:
   1548             u = 0xFFFFFFFF & con->Ico.U32;
   1549             break;
   1550          case Ico_U16:
   1551             u = 0x0000FFFF & con->Ico.U16;
   1552             break;
   1553          case Ico_U8:
   1554             u = 0x000000FF & con->Ico.U8;
   1555             break;
   1556          default:
   1557             vpanic("iselIntExpr_RH.Iex_Const(mips)");
   1558       }
   1559       l = (Long) u;
   1560       /* Now figure out if it's representable. */
   1561       if (!syned && u <= 65535) {
   1562          return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
   1563       }
   1564       if (syned && l >= -32767 && l <= 32767) {
   1565          return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
   1566       }
   1567       /* no luck; use the Slow Way. */
   1568    }
   1569    /* default case: calculate into a register and return that */
   1570    return MIPSRH_Reg(iselWordExpr_R(env, e));
   1571 }
   1572 
   1573 /* --------------------- RH5u --------------------- */
   1574 
   1575 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
   1576    being an immediate in the range 1 .. 31 inclusive.  Used for doing
   1577    shift amounts. */
   1578 
   1579 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
   1580 {
   1581    MIPSRH *ri;
   1582    ri = iselWordExpr_RH5u_wrk(env, e);
   1583    /* sanity checks ... */
   1584    switch (ri->tag) {
   1585       case Mrh_Imm:
   1586          vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
   1587          vassert(!ri->Mrh.Imm.syned);
   1588          return ri;
   1589       case Mrh_Reg:
   1590          vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
   1591          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
   1592          return ri;
   1593       default:
   1594          vpanic("iselIntExpr_RH5u: unknown mips RH tag");
   1595    }
   1596 }
   1597 
   1598 /* DO NOT CALL THIS DIRECTLY ! */
   1599 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
   1600 {
   1601    IRType ty = typeOfIRExpr(env->type_env, e);
   1602    vassert(ty == Ity_I8);
   1603 
   1604    /* special case: immediate */
   1605    if (e->tag == Iex_Const
   1606        && e->Iex.Const.con->tag == Ico_U8
   1607        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
   1608       return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
   1609    }
   1610 
   1611    /* default case: calculate into a register and return that */
   1612    return MIPSRH_Reg(iselWordExpr_R(env, e));
   1613 }
   1614 
   1615 /* --------------------- CONDCODE --------------------- */
   1616 
   1617 /* Generate code to evaluated a bit-typed expression, returning the
   1618    condition code which would correspond when the expression would
   1619    notionally have returned 1. */
   1620 
   1621 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
   1622 {
   1623    MIPSCondCode cc = iselCondCode_wrk(env,e);
   1624    vassert(cc != MIPScc_NV);
   1625    return cc;
   1626 }
   1627 
   1628 /* DO NOT CALL THIS DIRECTLY ! */
   1629 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
   1630 {
   1631    vassert(e);
   1632    vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
   1633    /* Cmp*32*(x,y) ? */
   1634    if (e->Iex.Binop.op == Iop_CmpEQ32
   1635        || e->Iex.Binop.op == Iop_CmpNE32
   1636        || e->Iex.Binop.op == Iop_CmpNE64
   1637        || e->Iex.Binop.op == Iop_CmpLT32S
   1638        || e->Iex.Binop.op == Iop_CmpLT32U
   1639        || e->Iex.Binop.op == Iop_CmpLT64U
   1640        || e->Iex.Binop.op == Iop_CmpLE32S
   1641        || e->Iex.Binop.op == Iop_CmpLE64S
   1642        || e->Iex.Binop.op == Iop_CmpLT64S
   1643        || e->Iex.Binop.op == Iop_CmpEQ64) {
   1644 
   1645       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
   1646                    || e->Iex.Binop.op == Iop_CmpLE32S
   1647                    || e->Iex.Binop.op == Iop_CmpLT64S
   1648                    || e->Iex.Binop.op == Iop_CmpLE64S);
   1649       Bool size32;
   1650       HReg dst = newVRegI(env);
   1651       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1652       HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1653 
   1654       MIPSCondCode cc;
   1655 
   1656       switch (e->Iex.Binop.op) {
   1657          case Iop_CmpEQ32:
   1658             cc = MIPScc_EQ;
   1659             size32 = True;
   1660             break;
   1661          case Iop_CmpNE32:
   1662             cc = MIPScc_NE;
   1663             size32 = True;
   1664             break;
   1665          case Iop_CmpNE64:
   1666             cc = MIPScc_NE;
   1667             size32 = True;
   1668             break;
   1669          case Iop_CmpLT32S:
   1670             cc = MIPScc_LT;
   1671             size32 = True;
   1672             break;
   1673          case Iop_CmpLT32U:
   1674             cc = MIPScc_LO;
   1675             size32 = True;
   1676             break;
   1677          case Iop_CmpLT64U:
   1678             cc = MIPScc_LO;
   1679             size32 = False;
   1680             break;
   1681          case Iop_CmpLE32S:
   1682             cc = MIPScc_LE;
   1683             size32 = True;
   1684             break;
   1685          case Iop_CmpLE64S:
   1686             cc = MIPScc_LE;
   1687             size32 = False;
   1688             break;
   1689          case Iop_CmpLT64S:
   1690             cc = MIPScc_LT;
   1691             size32 = False;
   1692             break;
   1693          case Iop_CmpEQ64:
   1694             cc = MIPScc_EQ;
   1695             size32 = False;
   1696             break;
   1697          default:
   1698             vpanic
   1699                 ("iselCondCode(mips): CmpXX32 or CmpXX64");
   1700       }
   1701 
   1702       addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
   1703       // Store result to guest_COND
   1704       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   1705 
   1706       addInstr(env, MIPSInstr_Store(4,
   1707                MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
   1708                dst, mode64));
   1709       return cc;
   1710    }
   1711    if (e->Iex.Binop.op == Iop_Not1) {
   1712       HReg r_dst = newVRegI(env);
   1713       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1714       MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   1715 
   1716       addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   1717       addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
   1718       // Store result to guest_COND
   1719       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   1720 
   1721       addInstr(env, MIPSInstr_Store(4,
   1722                MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
   1723                r_dst, mode64));
   1724       return MIPScc_NE;
   1725    }
   1726    if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
   1727       HReg r_dst = iselWordExpr_R_wrk(env, e);
   1728       // Store result to guest_COND
   1729       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   1730 
   1731       addInstr(env, MIPSInstr_Store(4,
   1732                MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
   1733                r_dst, mode64));
   1734       return MIPScc_EQ;
   1735    }
   1736 
   1737    vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
   1738    ppIRExpr(e);
   1739    vpanic("iselCondCode(mips)");
   1740 }
   1741 
   1742 /*---------------------------------------------------------*/
   1743 /*--- ISEL: Integer expressions (128 bit)               ---*/
   1744 /*---------------------------------------------------------*/
   1745 
   1746 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
   1747    which is returned as the first two parameters.  As with
   1748    iselWordExpr_R, these may be either real or virtual regs; in any
   1749    case they must not be changed by subsequent code emitted by the
   1750    caller.  */
   1751 
   1752 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   1753 {
   1754    vassert(env->mode64);
   1755    iselInt128Expr_wrk(rHi, rLo, env, e);
   1756 #  if 0
   1757    vex_printf("\n");
   1758    ppIRExpr(e);
   1759    vex_printf("\n");
   1760 #  endif
   1761    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
   1762    vassert(hregIsVirtual(*rHi));
   1763    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
   1764    vassert(hregIsVirtual(*rLo));
   1765 }
   1766 
   1767 /* DO NOT CALL THIS DIRECTLY ! */
   1768 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
   1769                                IRExpr * e)
   1770 {
   1771    vassert(e);
   1772    vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
   1773 
   1774    /* read 128-bit IRTemp */
   1775    if (e->tag == Iex_RdTmp) {
   1776       lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
   1777       return;
   1778    }
   1779 
   1780    /* --------- BINARY ops --------- */
   1781    if (e->tag == Iex_Binop) {
   1782       switch (e->Iex.Binop.op) {
   1783          /* 64 x 64 -> 128 multiply */
   1784          case Iop_MullU64:
   1785          case Iop_MullS64:
   1786             {
   1787                HReg tLo = newVRegI(env);
   1788                HReg tHi = newVRegI(env);
   1789                Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
   1790                HReg r_dst = newVRegI(env);
   1791                HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1792                HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1793                addInstr(env, MIPSInstr_Mul(syned, True, False /*64bit mul */ ,
   1794                                            r_dst, r_srcL, r_srcR));
   1795                addInstr(env, MIPSInstr_Mfhi(tHi));
   1796                addInstr(env, MIPSInstr_Mflo(tLo));
   1797                *rHi = tHi;
   1798                *rLo = tLo;
   1799                return;
   1800             }
   1801 
   1802          /* 64HLto128(e1,e2) */
   1803          case Iop_64HLto128:
   1804             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1805             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1806             return;
   1807 
   1808          case Iop_DivModS64to64: {
   1809             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1810             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1811             HReg tLo = newVRegI(env);
   1812             HReg tHi = newVRegI(env);
   1813             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
   1814 
   1815             addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
   1816             addInstr(env, MIPSInstr_Mfhi(tHi));
   1817             addInstr(env, MIPSInstr_Mflo(tLo));
   1818             *rHi = tHi;
   1819             *rLo = tLo;
   1820             return;
   1821          }
   1822 
   1823          case Iop_DivModU128to64: {
   1824             vassert(mode64);
   1825             HReg rHi1, rLo1;
   1826             iselInt128Expr(&rHi1, &rLo1, env, e->Iex.Binop.arg1);
   1827 
   1828             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1829             HReg tLo = newVRegI(env);
   1830             HReg tHi = newVRegI(env);
   1831             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS128to64);
   1832 
   1833             addInstr(env, MIPSInstr_Div(syned, False, rLo1, r_srcR));
   1834             addInstr(env, MIPSInstr_Mfhi(tHi));
   1835             addInstr(env, MIPSInstr_Mflo(tLo));
   1836             *rHi = tHi;
   1837             *rLo = tLo;
   1838             return;
   1839          }
   1840 
   1841          default:
   1842             break;
   1843       }
   1844    }
   1845    vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
   1846    ppIRExpr(e);
   1847    vpanic("iselInt128Expr(mips64)");
   1848 }
   1849 
   1850 /*---------------------------------------------------------*/
   1851 /*--- ISEL: Integer expressions (64 bit)                ---*/
   1852 /*---------------------------------------------------------*/
   1853 
   1854 /* 32-bit mode ONLY. Compute a 64-bit value into the register
   1855  * pair HI, LO. HI and LO must not be changed by subsequent
   1856  *  code emitted by the caller. */
   1857 
   1858 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   1859 {
   1860    vassert(!env->mode64);
   1861    iselInt64Expr_wrk(rHi, rLo, env, e);
   1862    vassert(hregClass(*rHi) == HRcInt32);
   1863    vassert(hregIsVirtual(*rHi));
   1864    vassert(hregClass(*rLo) == HRcInt32);
   1865    vassert(hregIsVirtual(*rLo));
   1866 }
   1867 
   1868 /* DO NOT CALL THIS DIRECTLY ! */
   1869 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   1870 {
   1871    vassert(e);
   1872    vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
   1873 
   1874    /* read 64-bit IRTemp */
   1875    if (e->tag == Iex_RdTmp) {
   1876       lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
   1877       return;
   1878    }
   1879    /* 64-bit load */
   1880    if (e->tag == Iex_Load) {
   1881       HReg tLo = newVRegI(env);
   1882       HReg tHi = newVRegI(env);
   1883       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
   1884       addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
   1885       addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
   1886       *rHi = tHi;
   1887       *rLo = tLo;
   1888       return;
   1889    }
   1890 
   1891    /* 64-bit literal */
   1892    if (e->tag == Iex_Const) {
   1893       ULong w64 = e->Iex.Const.con->Ico.U64;
   1894       UInt wHi = toUInt(w64 >> 32);
   1895       UInt wLo = toUInt(w64);
   1896       HReg tLo = newVRegI(env);
   1897       HReg tHi = newVRegI(env);
   1898       vassert(e->Iex.Const.con->tag == Ico_U64);
   1899 
   1900       if (wLo == wHi) {
   1901          /* Save a precious Int register in this special case. */
   1902          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
   1903          *rHi = tLo;
   1904          *rLo = tLo;
   1905       } else {
   1906          addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
   1907          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
   1908          *rHi = tHi;
   1909          *rLo = tLo;
   1910       }
   1911 
   1912       return;
   1913    }
   1914 
   1915    /* 64-bit GET */
   1916    if (e->tag == Iex_Get) {
   1917       HReg tLo = newVRegI(env);
   1918       HReg tHi = newVRegI(env);
   1919 
   1920       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   1921                                         GuestStatePointer(mode64));
   1922       addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
   1923       addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
   1924       *rHi = tHi;
   1925       *rLo = tLo;
   1926       return;
   1927    }
   1928 
   1929    /* 64-bit Mux0X */
   1930    if (e->tag == Iex_Mux0X) {
   1931       HReg expr0Lo, expr0Hi;
   1932       HReg exprXLo, exprXHi;
   1933       HReg tmpHi = newVRegI(env);
   1934       HReg tmpLo = newVRegI(env);
   1935       HReg tmp1Hi = newVRegI(env);
   1936       HReg tmp1Lo = newVRegI(env);
   1937       HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
   1938       HReg r_cond_neg = newVRegI(env);
   1939       HReg desLo = newVRegI(env);
   1940       HReg desHi = newVRegI(env);
   1941 
   1942       /* expr0Hi:expr0Lo = expr0 */
   1943       /* exprXHi:exprXLo = exprX */
   1944       iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.Mux0X.expr0);
   1945       iselInt64Expr(&exprXHi, &exprXLo, env, e->Iex.Mux0X.exprX);
   1946 
   1947       addInstr(env, MIPSInstr_Alu(Malu_AND, tmpLo, r_cond,
   1948                                   MIPSRH_Reg(exprXLo)));
   1949       addInstr(env, MIPSInstr_Alu(Malu_AND, tmpHi, r_cond,
   1950                                   MIPSRH_Reg(exprXHi)));
   1951       addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
   1952                                   MIPSRH_Reg(r_cond)));
   1953       addInstr(env, MIPSInstr_Alu(Malu_AND, tmp1Lo, r_cond_neg,
   1954                                   MIPSRH_Reg(exprXLo)));
   1955       addInstr(env, MIPSInstr_Alu(Malu_AND, tmp1Hi, r_cond_neg,
   1956                                   MIPSRH_Reg(exprXHi)));
   1957       addInstr(env, MIPSInstr_Alu(Malu_ADD, desLo, tmpLo,
   1958                                   MIPSRH_Reg(tmp1Lo)));
   1959       addInstr(env, MIPSInstr_Alu(Malu_ADD, desHi, tmpHi,
   1960                                   MIPSRH_Reg(tmp1Hi)));
   1961       *rHi = desHi;
   1962       *rLo = desLo;
   1963       return;
   1964    }
   1965 
   1966    /* --------- BINARY ops --------- */
   1967    if (e->tag == Iex_Binop) {
   1968       IROp op_binop = e->Iex.Binop.op;
   1969       switch (op_binop) {
   1970          /* 32 x 32 -> 64 multiply */
   1971          /* Add64 */
   1972          case Iop_Add64: {
   1973             HReg xLo, xHi, yLo, yHi;
   1974             HReg tHi = newVRegI(env);
   1975             HReg tLo = newVRegI(env);
   1976             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
   1977             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
   1978             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, xHi, MIPSRH_Reg(yHi)));
   1979             addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
   1980             *rHi = tHi;
   1981             *rLo = tLo;
   1982             return;
   1983          }
   1984          case Iop_MullU32:
   1985          case Iop_MullS32: {
   1986             HReg tLo = newVRegI(env);
   1987             HReg tHi = newVRegI(env);
   1988             HReg r_dst = newVRegI(env);
   1989             Bool syned = toBool(op_binop == Iop_MullS32);
   1990             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1991             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1992 
   1993             addInstr(env, MIPSInstr_Mul(syned/*Unsigned or Signed */ ,
   1994                                         True /*widen */ , True,
   1995                                         r_dst, r_srcL, r_srcR));
   1996             addInstr(env, MIPSInstr_Mfhi(tHi));
   1997             addInstr(env, MIPSInstr_Mflo(tLo));
   1998             *rHi = tHi;
   1999             *rLo = tLo;
   2000 
   2001             return;
   2002          }
   2003          case Iop_DivModS64to32:
   2004          case Iop_DivModU64to32: {
   2005             HReg r_sHi, r_sLo;
   2006             HReg tLo = newVRegI(env);
   2007             HReg tHi = newVRegI(env);
   2008             Bool syned = toBool(op_binop == Iop_DivModS64to32);
   2009             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2010 
   2011             iselInt64Expr(&r_sHi, &r_sLo, env, e->Iex.Binop.arg1);
   2012             addInstr(env, MIPSInstr_Div(syned, True, r_sLo, r_srcR));
   2013             addInstr(env, MIPSInstr_Mfhi(tHi));
   2014             addInstr(env, MIPSInstr_Mflo(tLo));
   2015             *rHi = tHi;
   2016             *rLo = tLo;
   2017 
   2018             return;
   2019          }
   2020 
   2021             /* 32HLto64(e1,e2) */
   2022          case Iop_32HLto64:
   2023             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2024             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2025 
   2026             return;
   2027             /* Or64/And64/Xor64 */
   2028          case Iop_Or64:
   2029          case Iop_And64:
   2030          case Iop_Xor64: {
   2031             HReg xLo, xHi, yLo, yHi;
   2032             HReg tLo = newVRegI(env);
   2033             HReg tHi = newVRegI(env);
   2034             MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
   2035                            (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
   2036             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
   2037             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
   2038             addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
   2039             addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
   2040             *rHi = tHi;
   2041             *rLo = tLo;
   2042             return;
   2043          }
   2044 
   2045          default:
   2046             break;
   2047       }
   2048    }
   2049 
   2050    /* --------- UNARY ops --------- */
   2051    if (e->tag == Iex_Unop) {
   2052 
   2053       switch (e->Iex.Unop.op) {
   2054          case Iop_1Sto64: {
   2055             HReg tLo = newVRegI(env);
   2056             HReg tHi = newVRegI(env);
   2057             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2058             HReg tmp = newVRegI(env);
   2059 
   2060             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
   2061                           MIPSRH_Imm(False, 31)));
   2062             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, src,
   2063                           MIPSRH_Imm(False, 31)));
   2064 
   2065             addInstr(env, mk_iMOVds_RR(tHi, tmp));
   2066             addInstr(env, mk_iMOVds_RR(tLo, tmp));
   2067 
   2068             *rHi = tHi;
   2069             *rLo = tLo;
   2070             return;
   2071          }
   2072 
   2073          /* 32Sto64(e) */
   2074          case Iop_32Sto64: {
   2075             HReg tLo = newVRegI(env);
   2076             HReg tHi = newVRegI(env);
   2077             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2078             addInstr(env, mk_iMOVds_RR(tHi, src));
   2079             addInstr(env, mk_iMOVds_RR(tLo, src));
   2080             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
   2081                           MIPSRH_Imm(False, 31)));
   2082             *rHi = tHi;
   2083             *rLo = tLo;
   2084             return;
   2085          }
   2086 
   2087          /* 32Uto64(e) */
   2088          case Iop_32Uto64: {
   2089             HReg tLo = newVRegI(env);
   2090             HReg tHi = newVRegI(env);
   2091             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2092             addInstr(env, mk_iMOVds_RR(tLo, src));
   2093             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
   2094                           MIPSRH_Reg(hregMIPS_GPR0(mode64))));
   2095             *rHi = tHi;
   2096             *rLo = tLo;
   2097             return;
   2098          }
   2099 
   2100          case Iop_CmpwNEZ64: {
   2101             HReg srcLo, srcHi;
   2102             HReg tmp1 = newVRegI(env);
   2103             HReg tmp2 = newVRegI(env);
   2104             /* srcHi:srcLo = arg */
   2105             iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
   2106             /* tmp1 = srcHi | srcLo */
   2107             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
   2108                                         MIPSRH_Reg(srcHi)));
   2109             /* tmp2 = (tmp1 | -tmp1) >>s 31 */
   2110 
   2111             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
   2112                                         MIPSRH_Reg(tmp1)));
   2113 
   2114             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
   2115             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
   2116                           MIPSRH_Imm(False, 31)));
   2117             *rHi = tmp2;
   2118             *rLo = tmp2;
   2119             return;
   2120 
   2121          }
   2122          case Iop_ReinterpF64asI64: {
   2123             HReg tLo = newVRegI(env);
   2124             HReg tHi = newVRegI(env);
   2125             MIPSAMode *am_addr;
   2126             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
   2127 
   2128             sub_from_sp(env, 16);   // Move SP down 16 bytes
   2129             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2130 
   2131             // store as F64
   2132             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   2133                                            am_addr));
   2134             // load as 2xI32
   2135             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
   2136             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
   2137                                          mode64));
   2138 
   2139             add_to_sp(env, 16);  // Reset SP
   2140 
   2141             *rHi = tHi;
   2142             *rLo = tLo;
   2143             return;
   2144          }
   2145 
   2146          default:
   2147             vex_printf("UNARY: No such op: ");
   2148             ppIROp(e->Iex.Unop.op);
   2149             vex_printf("\n");
   2150             break;
   2151       }
   2152    }
   2153 
   2154    vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
   2155    ppIRExpr(e);
   2156    vpanic("iselInt64Expr(mips)");
   2157 }
   2158 
   2159 /*---------------------------------------------------------*/
   2160 /*--- ISEL: Floating point expressions (32 bit)         ---*/
   2161 /*---------------------------------------------------------*/
   2162 
   2163 /* Nothing interesting here; really just wrappers for
   2164    64-bit stuff. */
   2165 
   2166 static HReg iselFltExpr(ISelEnv * env, IRExpr * e)
   2167 {
   2168    HReg r = iselFltExpr_wrk(env, e);
   2169    vassert(hregIsVirtual(r));
   2170    return r;
   2171 }
   2172 
   2173 /* DO NOT CALL THIS DIRECTLY */
   2174 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
   2175 {
   2176    IRType ty = typeOfIRExpr(env->type_env, e);
   2177    vassert(ty == Ity_F32 || (ty == Ity_F64 && mode64));
   2178 
   2179    if (e->tag == Iex_RdTmp) {
   2180       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   2181    }
   2182 
   2183    if (e->tag == Iex_Load) {
   2184       MIPSAMode *am_addr;
   2185       HReg r_dst = newVRegF(env);
   2186       vassert(e->Iex.Load.ty == Ity_F32
   2187              || (e->Iex.Load.ty == Ity_F64 && mode64));
   2188       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
   2189       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
   2190       return r_dst;
   2191    }
   2192 
   2193    if (e->tag == Iex_Get) {
   2194       HReg r_dst = newVRegF(env);
   2195       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   2196                                         GuestStatePointer(mode64));
   2197       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
   2198       return r_dst;
   2199    }
   2200 
   2201    if (e->tag == Iex_Unop) {
   2202       switch (e->Iex.Unop.op) {
   2203       case Iop_ReinterpI32asF32: {
   2204          MIPSAMode *am_addr;
   2205          HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2206          HReg r_dst = newVRegF(env);
   2207 
   2208          sub_from_sp(env, 16);   // Move SP down 16 bytes
   2209          am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2210 
   2211          // store as I32
   2212          addInstr(env, MIPSInstr_Store(4, am_addr, fr_src, mode64));
   2213 
   2214          // load as Ity_F32
   2215          addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
   2216 
   2217          add_to_sp(env, 16);  // Reset SP
   2218          return r_dst;
   2219 
   2220       }
   2221       case Iop_F32toF64: {
   2222          /* first arg is rounding mode; we ignore it. */
   2223          MIPSAMode *am_addr;
   2224          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   2225          HReg dst = newVRegF(env);
   2226 
   2227          sub_from_sp(env, 16);   // Move SP down 16 bytes
   2228          am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2229 
   2230          addInstr(env, MIPSInstr_Store(4,
   2231                                        MIPSAMode_IR(am_addr->Mam.IR.index + 4,
   2232                                        am_addr->Mam.IR.base),
   2233                                        hregMIPS_GPR0(mode64), mode64));
   2234          addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, src, am_addr));
   2235 
   2236          // load as Ity_F32
   2237          addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, dst, am_addr));
   2238          add_to_sp(env, 16);  // Reset SP
   2239 
   2240          return dst;
   2241       }
   2242       case Iop_ReinterpI64asF64:
   2243          {
   2244             vassert(mode64);
   2245             MIPSAMode *am_addr;
   2246             HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2247             HReg r_dst = newVRegF(env);
   2248 
   2249             sub_from_sp(env, 16);   // Move SP down 16 bytes
   2250             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2251 
   2252             // store as I32
   2253             addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
   2254 
   2255             // load as Ity_F32
   2256             addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   2257 
   2258             add_to_sp(env, 16);  // Reset SP
   2259             return r_dst;
   2260          }
   2261       case Iop_AbsF32:
   2262       case Iop_AbsF64: {
   2263          Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
   2264          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   2265          HReg dst = newVRegF(env);
   2266          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
   2267          return dst;
   2268       }
   2269       case Iop_NegF32:
   2270       case Iop_NegF64: {
   2271          Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
   2272          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   2273          HReg dst = newVRegF(env);
   2274          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
   2275          return dst;
   2276       }
   2277       default:
   2278          break;
   2279       }
   2280    }
   2281 
   2282    if (e->tag == Iex_Triop) {
   2283       switch (e->Iex.Triop.details->op) {
   2284          case Iop_DivF32:
   2285          case Iop_DivF64:
   2286          case Iop_MulF32:
   2287          case Iop_MulF64:
   2288          case Iop_AddF32:
   2289          case Iop_AddF64:
   2290          case Iop_SubF32:
   2291          case Iop_SubF64: {
   2292             MIPSFpOp op = 0;
   2293             /*INVALID*/ HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
   2294             HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
   2295             HReg dst = newVRegF(env);
   2296             switch (e->Iex.Triop.details->op) {
   2297                case Iop_DivF32:
   2298                   op = Mfp_DIVS;
   2299                   break;
   2300                case Iop_MulF32:
   2301                   op = Mfp_MULS;
   2302                   break;
   2303                case Iop_AddF32:
   2304                   op = Mfp_ADDS;
   2305                   break;
   2306                case Iop_SubF32:
   2307                   op = Mfp_SUBS;
   2308                   break;
   2309                default:
   2310                   vassert(0);
   2311             }
   2312             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
   2313             return dst;
   2314          }
   2315          default:
   2316             break;
   2317       }
   2318    }
   2319 
   2320    if (e->tag == Iex_Binop) {
   2321       switch (e->Iex.Binop.op) {
   2322          case Iop_F64toF32: {
   2323             HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
   2324             HReg valS = newVRegF(env);
   2325 
   2326             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2327             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
   2328             set_MIPS_rounding_default(env);
   2329             return valS;
   2330          }
   2331 
   2332          case Iop_RoundF32toInt: {
   2333                HReg valS = newVRegF(env);
   2334                HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
   2335 
   2336                set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2337                addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
   2338 
   2339                set_MIPS_rounding_default(env);
   2340                return valS;
   2341             }
   2342 
   2343          case Iop_I32StoF32: {
   2344             HReg r_dst = newVRegF(env);
   2345 
   2346             MIPSAMode *am_addr;
   2347             HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2348             HReg tmp = newVRegF(env);
   2349 
   2350             sub_from_sp(env, 16);   // Move SP down 16 bytes
   2351             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2352 
   2353             // store as I32
   2354             addInstr(env, MIPSInstr_Store(4, am_addr, fr_src, mode64));
   2355 
   2356             // load as Ity_F32
   2357             addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, tmp, am_addr));
   2358 
   2359             add_to_sp(env, 16);  // Reset SP
   2360 
   2361             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2362             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
   2363             set_MIPS_rounding_default(env);
   2364 
   2365             return r_dst;
   2366          }
   2367 
   2368          case Iop_SqrtF32:
   2369          case Iop_SqrtF64: {
   2370             /* first arg is rounding mode; we ignore it. */
   2371             Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
   2372             HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
   2373             HReg dst = newVRegF(env);
   2374             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2375             addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
   2376                                             src));
   2377             set_MIPS_rounding_default(env);
   2378             return dst;
   2379          }
   2380 
   2381          default:
   2382             break;
   2383       }
   2384    }
   2385 
   2386    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
   2387       /* This is quite subtle.  The only way to do the relevant
   2388          truncation is to do a single-precision store and then a
   2389          double precision load to get it back into a register.  The
   2390          problem is, if the data is then written to memory a second
   2391          time, as in
   2392 
   2393          STbe(...) = TruncF64asF32(...)
   2394 
   2395          then will the second truncation further alter the value?  The
   2396          answer is no: flds (as generated here) followed by fsts
   2397          (generated for the STbe) is the identity function on 32-bit
   2398          floats, so we are safe.
   2399 
   2400          Another upshot of this is that if iselStmt can see the
   2401          entirety of
   2402 
   2403          STbe(...) = TruncF64asF32(arg)
   2404 
   2405          then it can short circuit having to deal with TruncF64asF32
   2406          individually; instead just compute arg into a 64-bit FP
   2407          register and do 'fsts' (since that itself does the
   2408          truncation).
   2409 
   2410          We generate pretty poor code here (should be ok both for
   2411          32-bit and 64-bit mode); but it is expected that for the most
   2412          part the latter optimisation will apply and hence this code
   2413          will not often be used.
   2414        */
   2415       HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
   2416       HReg fdst = newVRegF(env);
   2417       MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
   2418 
   2419       sub_from_sp(env, 16);
   2420       // store as F32, hence truncating
   2421       addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
   2422       // and reload.  Good huh?! (sigh)
   2423       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
   2424       add_to_sp(env, 16);
   2425       return fdst;
   2426    }
   2427 
   2428    vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
   2429    ppIRExpr(e);
   2430    vpanic("iselFltExpr_wrk(mips)");
   2431 }
   2432 
   2433 static HReg iselDblExpr(ISelEnv * env, IRExpr * e)
   2434 {
   2435    HReg r = iselDblExpr_wrk(env, e);
   2436    vassert(hregClass(r) == HRcFlt64);
   2437    vassert(hregIsVirtual(r));
   2438    return r;
   2439 }
   2440 
   2441 /* DO NOT CALL THIS DIRECTLY */
   2442 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
   2443 {
   2444    IRType ty = typeOfIRExpr(env->type_env, e);
   2445    vassert(e);
   2446    vassert(ty == Ity_F64);
   2447 
   2448    if (e->tag == Iex_RdTmp) {
   2449       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   2450    }
   2451 
   2452    /* --------- LOAD --------- */
   2453    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
   2454       HReg r_dst = newVRegD(env);
   2455       MIPSAMode *am_addr;
   2456       vassert(e->Iex.Load.ty == Ity_F64);
   2457       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
   2458       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   2459       return r_dst;
   2460    }
   2461 
   2462    /* --------- GET --------- */
   2463    if (e->tag == Iex_Get) {
   2464 
   2465       HReg r_dst = newVRegD(env);
   2466       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   2467                                         GuestStatePointer(mode64));
   2468       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   2469       return r_dst;
   2470    }
   2471 
   2472    if (e->tag == Iex_Unop) {
   2473       MIPSFpOp fpop = Mfp_INVALID;
   2474       switch (e->Iex.Unop.op) {
   2475          case Iop_NegF64:
   2476             fpop = Mfp_NEGD;
   2477             break;
   2478          case Iop_AbsF64:
   2479             fpop = Mfp_ABSD;
   2480             break;
   2481          case Iop_F32toF64: {
   2482             HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   2483             HReg dst = newVRegD(env);
   2484 
   2485             HReg irrm = newVRegI(env);
   2486 
   2487             MIPSAMode *am_addr1 = MIPSAMode_IR(284, GuestStatePointer(mode64));
   2488 
   2489             addInstr(env, MIPSInstr_Load(4, irrm, am_addr1, mode64));
   2490 
   2491             // set new FCSR
   2492             HReg tmp = newVRegI(env);
   2493             HReg fcsr_old = newVRegI(env);
   2494             MIPSAMode *am_addr;
   2495 
   2496             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
   2497                                         MIPSRH_Imm(False, 1)));
   2498             addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
   2499             addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp,
   2500                                         MIPSRH_Imm(False, 3)));
   2501             /* save old value of FCSR */
   2502             addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
   2503             sub_from_sp(env, 8); // Move SP down 4 bytes
   2504             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2505 
   2506             //store old FCSR to stack
   2507             addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
   2508 
   2509             //set new value of FCSR
   2510             addInstr(env, MIPSInstr_MtFCSR(irrm));
   2511 
   2512             //set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2513             addInstr(env, MIPSInstr_FpUnary(Mfp_CVTD, dst, src));
   2514             set_MIPS_rounding_default(env);
   2515             return dst;
   2516          }
   2517          case Iop_ReinterpI64asF64: {
   2518             HReg Hi;
   2519             HReg Lo;
   2520             HReg dst = newVRegD(env);
   2521 
   2522             iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
   2523 
   2524             dst = mk_LoadRR32toFPR(env, Hi, Lo);   // 2*I32 -> F64
   2525             return dst;
   2526          }
   2527          case Iop_I32StoF64: {
   2528             HReg dst = newVRegD(env);
   2529             HReg tmp1 = newVRegF(env);
   2530             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2531             MIPSAMode *am_addr;
   2532             sub_from_sp(env, 16);   // Move SP down 16 bytes
   2533             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2534 
   2535             // store as I32
   2536             addInstr(env, MIPSInstr_Store(4, am_addr, r_src, mode64));
   2537 
   2538             // load as Ity_F32
   2539             addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, tmp1, am_addr));
   2540 
   2541             add_to_sp(env, 16);  // Reset SP
   2542 
   2543             HReg irrm = newVRegI(env);
   2544 
   2545             MIPSAMode *am_addr1 = MIPSAMode_IR(284, GuestStatePointer(mode64));
   2546 
   2547             addInstr(env, MIPSInstr_Load(4, irrm, am_addr1, mode64));
   2548 
   2549             //set rounding mode
   2550             HReg tmp = newVRegI(env);
   2551             HReg fcsr_old = newVRegI(env);
   2552 
   2553             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
   2554                                          MIPSRH_Imm(False, 1)));
   2555             addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
   2556             addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp,
   2557                                         MIPSRH_Imm(False, 3)));
   2558             /* save old value of FCSR */
   2559             addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
   2560             sub_from_sp(env, 8); // Move SP down 4 bytes
   2561             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2562 
   2563             //store old FCSR to stack
   2564             addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
   2565 
   2566             //set new value of FCSR
   2567             addInstr(env, MIPSInstr_MtFCSR(irrm));
   2568 
   2569             // and do convert
   2570             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp1));
   2571             set_MIPS_rounding_default(env);
   2572 
   2573             return dst;
   2574          }
   2575          default:
   2576             break;
   2577       }
   2578 
   2579       if (fpop != Mfp_INVALID) {
   2580          HReg src = iselDblExpr(env, e->Iex.Unop.arg);
   2581          HReg dst = newVRegD(env);
   2582          addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
   2583          return dst;
   2584       }
   2585    }
   2586 
   2587    if (e->tag == Iex_Binop) {
   2588       switch (e->Iex.Binop.op) {
   2589          case Iop_RoundF64toInt: {
   2590             HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
   2591             MIPSRH *fmt = iselWordExpr_RH(env, False, e->Iex.Binop.arg1);
   2592             HReg valD1 = newVRegD(env);
   2593 
   2594             if (fmt->Mrh.Imm.imm16 == 0x3)
   2595                addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, valD1, valD));
   2596             else if (fmt->Mrh.Imm.imm16 == 0x2)
   2597                addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, valD1, valD));
   2598             else
   2599                vassert(0);
   2600             return valD1;
   2601          }
   2602 
   2603          case Iop_SqrtF64:{
   2604             /* first arg is rounding mode; we ignore it. */
   2605             HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
   2606             HReg dst = newVRegD(env);
   2607             addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
   2608             return dst;
   2609          }
   2610 
   2611          default:
   2612             break;
   2613 
   2614       }
   2615    }
   2616 
   2617    if (e->tag == Iex_Triop) {
   2618       switch (e->Iex.Triop.details->op) {
   2619          case Iop_DivF64:
   2620          case Iop_DivF32:
   2621          case Iop_MulF64:
   2622          case Iop_AddF64:
   2623          case Iop_SubF64: {
   2624             MIPSFpOp op = 0;
   2625             /*INVALID*/ HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
   2626             HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
   2627             HReg dst = newVRegD(env);
   2628             switch (e->Iex.Triop.details->op) {
   2629                case Iop_DivF64:
   2630                   op = Mfp_DIVD;
   2631                   break;
   2632                case Iop_MulF64:
   2633                   op = Mfp_MULD;
   2634                   break;
   2635                case Iop_AddF64:
   2636                   op = Mfp_ADDD;
   2637                   break;
   2638                case Iop_SubF64:
   2639                   op = Mfp_SUBD;
   2640                   break;
   2641                default:
   2642                   vassert(0);
   2643             }
   2644             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
   2645             return dst;
   2646          }
   2647          default:
   2648             break;
   2649       }
   2650    }
   2651 
   2652    /* --------- MULTIPLEX --------- */
   2653    if (e->tag == Iex_Mux0X) {
   2654       if (ty == Ity_F64
   2655           && typeOfIRExpr(env->type_env, e->Iex.Mux0X.cond) == Ity_I8) {
   2656          HReg r0 = iselDblExpr(env, e->Iex.Mux0X.expr0);
   2657          HReg rX = iselDblExpr(env, e->Iex.Mux0X.exprX);
   2658          HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
   2659          HReg r_cond_neg = newVRegI(env);
   2660          HReg r_dst = newVRegD(env);
   2661          HReg r_tmp_lo = newVRegI(env);
   2662          HReg r_tmp_hi = newVRegI(env);
   2663          HReg r_tmp1_lo = newVRegI(env);
   2664          HReg r_tmp1_hi = newVRegI(env);
   2665          HReg r_r0_lo = newVRegI(env);
   2666          HReg r_r0_hi = newVRegI(env);
   2667          HReg r_rX_lo = newVRegI(env);
   2668          HReg r_rX_hi = newVRegI(env);
   2669          HReg r_dst_lo = newVRegI(env);
   2670          HReg r_dst_hi = newVRegI(env);
   2671 
   2672          sub_from_sp(env, 16);   // Move SP down 16 bytes
   2673          MIPSAMode *am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2674 
   2675          // store as Ity_F64
   2676          addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, r0, am_addr));
   2677 
   2678          // load as 2xI32
   2679          addInstr(env, MIPSInstr_Load(4, r_r0_lo, am_addr, mode64));
   2680          addInstr(env, MIPSInstr_Load(4, r_r0_hi, nextMIPSAModeFloat(am_addr),
   2681                                       mode64));
   2682 
   2683          add_to_sp(env, 16);  // Reset SP
   2684 
   2685          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp_lo, r_cond,
   2686                                      MIPSRH_Reg(r_r0_lo)));
   2687          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp_hi, r_cond,
   2688                        MIPSRH_Reg(r_r0_hi)));
   2689 
   2690          addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
   2691                        MIPSRH_Reg(r_cond)));
   2692 
   2693          sub_from_sp(env, 16);   // Move SP down 16 bytes
   2694          am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2695 
   2696          // store as Ity_F64
   2697          addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, rX, am_addr));
   2698 
   2699          // load as 2xI32
   2700          addInstr(env, MIPSInstr_Load(4, r_rX_lo, am_addr, mode64));
   2701          addInstr(env, MIPSInstr_Load(4, r_rX_hi, nextMIPSAModeFloat(am_addr),
   2702                                       mode64));
   2703 
   2704          add_to_sp(env, 16);  // Reset SP
   2705 
   2706          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1_lo, r_cond_neg,
   2707                                      MIPSRH_Reg(r_rX_lo)));
   2708          addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1_hi, r_cond_neg,
   2709                                      MIPSRH_Reg(r_rX_hi)));
   2710 
   2711          addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst_lo, r_tmp_lo,
   2712                                      MIPSRH_Reg(r_tmp1_lo)));
   2713          addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst_hi, r_tmp_hi,
   2714                                      MIPSRH_Reg(r_tmp1_hi)));
   2715 
   2716          sub_from_sp(env, 16);   // Move SP down 16 bytes
   2717          am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2718 
   2719          // store as I32
   2720          addInstr(env, MIPSInstr_Store(4, am_addr, r_dst_lo, mode64));
   2721          addInstr(env, MIPSInstr_Store(4, nextMIPSAModeFloat(am_addr),
   2722                   r_dst_hi, mode64));
   2723 
   2724          // load as Ity_F32
   2725          addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   2726 
   2727          add_to_sp(env, 16);  // Reset SP
   2728 
   2729          return r_dst;
   2730       }
   2731    }
   2732 
   2733    vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
   2734    ppIRExpr(e);
   2735    vpanic("iselDblExpr_wrk(mips)");
   2736 }
   2737 
   2738 /*---------------------------------------------------------*/
   2739 /*--- ISEL: Statements                                  ---*/
   2740 /*---------------------------------------------------------*/
   2741 
   2742 static void iselStmt(ISelEnv * env, IRStmt * stmt)
   2743 {
   2744    if (vex_traceflags & VEX_TRACE_VCODE) {
   2745       vex_printf("\n-- ");
   2746 
   2747       ppIRStmt(stmt);
   2748       vex_printf("\n");
   2749    }
   2750 
   2751    switch (stmt->tag) {
   2752       /* --------- STORE --------- */
   2753       case Ist_Store: {
   2754          MIPSAMode *am_addr;
   2755          IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   2756 
   2757          /*constructs addressing mode from address provided */
   2758          am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
   2759 
   2760          if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
   2761              (mode64 && (tyd == Ity_I64))) {
   2762             HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
   2763             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
   2764                      am_addr, r_src, mode64));
   2765             return;
   2766          }
   2767          if (!mode64 && (tyd == Ity_I64)) {
   2768             HReg vHi, vLo;
   2769             HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
   2770 
   2771             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
   2772 
   2773             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   2774                           MIPSAMode_IR(0, r_addr), vHi, mode64));
   2775             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   2776                           MIPSAMode_IR(4, r_addr), vLo, mode64));
   2777             return;
   2778          }
   2779          if (tyd == Ity_F32) {
   2780             HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
   2781             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
   2782                                            am_addr));
   2783             return;
   2784          }
   2785 
   2786          break;
   2787       }
   2788 
   2789       /* --------- PUT --------- */
   2790       case Ist_Put: {
   2791          IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   2792 
   2793          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   2794              (ty == Ity_I64 && mode64)) {
   2795             HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
   2796             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   2797                                               GuestStatePointer(mode64));
   2798             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
   2799                                           am_addr, r_src, mode64));
   2800             return;
   2801          }
   2802 
   2803          if (ty == Ity_I64 && !mode64) {
   2804             HReg vHi, vLo;
   2805             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   2806                                               GuestStatePointer(mode64));
   2807             MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
   2808                                                GuestStatePointer(mode64));
   2809             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
   2810             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   2811                                           am_addr, vLo, mode64));
   2812             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   2813                                           am_addr4, vHi, mode64));
   2814             return;
   2815 
   2816          }
   2817 
   2818          if (ty == Ity_F32) {
   2819             HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
   2820             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   2821                                               GuestStatePointer(mode64));
   2822             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
   2823                                            am_addr));
   2824             return;
   2825          }
   2826 
   2827          if (ty == Ity_F64) {
   2828             HReg fr_src;
   2829             fr_src = iselDblExpr(env, stmt->Ist.Put.data);
   2830             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   2831                                               GuestStatePointer(mode64));
   2832             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   2833                                            am_addr));
   2834             return;
   2835          }
   2836          break;
   2837       }
   2838 
   2839       /* --------- TMP --------- */
   2840       case Ist_WrTmp: {
   2841          IRTemp tmp = stmt->Ist.WrTmp.tmp;
   2842          IRType ty = typeOfIRTemp(env->type_env, tmp);
   2843 
   2844          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
   2845             HReg r_dst = lookupIRTemp(env, tmp);
   2846             HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
   2847             addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   2848             return;
   2849          }
   2850 
   2851          if (ty == Ity_I64) {
   2852              HReg rHi, rLo, dstHi, dstLo;
   2853              iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
   2854              lookupIRTemp64(&dstHi, &dstLo, env, tmp);
   2855              addInstr(env, mk_iMOVds_RR(dstHi, rHi));
   2856              addInstr(env, mk_iMOVds_RR(dstLo, rLo));
   2857              return;
   2858          }
   2859 
   2860          if (ty == Ity_F32) {
   2861             HReg fr_dst = lookupIRTemp(env, tmp);
   2862             HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
   2863             addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
   2864             return;
   2865          }
   2866 
   2867          if (ty == Ity_F64) {
   2868              HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
   2869              HReg dst = lookupIRTemp(env, tmp);
   2870              addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
   2871              return;
   2872          }
   2873          break;
   2874       }
   2875 
   2876       /* --------- Call to DIRTY helper --------- */
   2877       case Ist_Dirty: {
   2878          IRType retty;
   2879          IRDirty *d = stmt->Ist.Dirty.details;
   2880          Bool passBBP = False;
   2881 
   2882          if (d->nFxState == 0)
   2883             vassert(!d->needsBBP);
   2884          passBBP = toBool(d->nFxState > 0 && d->needsBBP);
   2885 
   2886          /* Marshal args, do the call, clear stack. */
   2887          doHelperCall(env, passBBP, d->guard, d->cee, d->args);
   2888 
   2889          /* Now figure out what to do with the returned value, if any. */
   2890          if (d->tmp == IRTemp_INVALID)
   2891             /* No return value.  Nothing to do. */
   2892             return;
   2893 
   2894          retty = typeOfIRTemp(env->type_env, d->tmp);
   2895          if (retty == Ity_I64 && !mode64) {
   2896             vex_printf
   2897                 ("Dirty! Return 64 bits. Not implemented (yet!)\n");
   2898             return;
   2899          }
   2900          if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32
   2901              || (retty == Ity_I64 && mode64)) {
   2902             /* The returned value is in %r2.  Park it in the register
   2903                associated with tmp. */
   2904             HReg r_dst = lookupIRTemp(env, d->tmp);
   2905             addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
   2906             return;
   2907          }
   2908          break;
   2909       }
   2910 
   2911       /* --------- Load Linked or Store Conditional --------- */
   2912       case Ist_LLSC: {
   2913          //Temporary solution; this need to be rewritten again for MIPS.
   2914          //On MIPS you can not read from address that is locked with LL before SC.
   2915          // If you read from address that is locked than SC will fall.
   2916          IRTemp res = stmt->Ist.LLSC.result;
   2917          IRType tyRes = typeOfIRTemp(env->type_env, res);
   2918          IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
   2919 
   2920          if (!mode64 && (tyAddr != Ity_I32))
   2921             goto stmt_fail;
   2922 
   2923          if (stmt->Ist.LLSC.storedata == NULL) {
   2924             /* LL */
   2925             MIPSAMode *r_addr;
   2926             /*constructs addressing mode from address provided */
   2927             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
   2928 
   2929             HReg r_dst = lookupIRTemp(env, res);
   2930             if (tyRes == Ity_I32) {
   2931                addInstr(env, MIPSInstr_Load(4, r_dst, r_addr, mode64));
   2932                return;
   2933             } else if (tyRes == Ity_I64 && mode64) {
   2934                addInstr(env, MIPSInstr_Load(8, r_dst, r_addr, mode64));
   2935                return;
   2936             }
   2937             /* fallthru */ ;
   2938          } else {
   2939             /* SC */
   2940             MIPSAMode *r_addr;
   2941             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
   2942             HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
   2943             HReg r_dst = lookupIRTemp(env, res);
   2944             IRType tyData = typeOfIRExpr(env->type_env,
   2945                                          stmt->Ist.LLSC.storedata);
   2946 
   2947             if (tyData == Ity_I32) {
   2948                addInstr(env, MIPSInstr_Store(4, r_addr, r_src, mode64));
   2949                addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   2950                return;
   2951             } else if (tyData == Ity_I64 && mode64) {
   2952                addInstr(env, MIPSInstr_Store(8, r_addr, r_src, mode64));
   2953                addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   2954                return;
   2955             }
   2956             /* fallthru */
   2957          }
   2958          goto stmt_fail;
   2959        /*NOTREACHED*/}
   2960 
   2961       /* --------- INSTR MARK --------- */
   2962       /* Doesn't generate any executable code ... */
   2963    case Ist_IMark:
   2964       return;
   2965 
   2966       /* --------- ABI HINT --------- */
   2967       /* These have no meaning (denotation in the IR) and so we ignore
   2968          them ... if any actually made it this far. */
   2969    case Ist_AbiHint:
   2970       return;
   2971 
   2972       /* --------- NO-OP --------- */
   2973       /* Fairly self-explanatory, wouldn't you say? */
   2974    case Ist_NoOp:
   2975       return;
   2976 
   2977    /* --------- EXIT --------- */
   2978    case Ist_Exit: {
   2979       IRConst* dst = stmt->Ist.Exit.dst;
   2980       if (!mode64 && dst->tag != Ico_U32)
   2981          vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
   2982       if (mode64 && dst->tag != Ico_U64)
   2983          vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
   2984 
   2985       MIPSCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
   2986       MIPSAMode*   amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
   2987                                       hregMIPS_GPR10(mode64));
   2988 
   2989       /* Case: boring transfer to known address */
   2990       if (stmt->Ist.Exit.jk == Ijk_Boring
   2991           || stmt->Ist.Exit.jk == Ijk_Call
   2992           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
   2993          if (env->chainingAllowed) {
   2994             /* .. almost always true .. */
   2995             /* Skip the event check at the dst if this is a forwards
   2996                edge. */
   2997             Bool toFastEP
   2998                = mode64
   2999                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
   3000                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
   3001             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
   3002             addInstr(env, MIPSInstr_XDirect(
   3003                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
   3004                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
   3005                              amPC, cc, toFastEP));
   3006          } else {
   3007             /* .. very occasionally .. */
   3008             /* We can't use chaining, so ask for an assisted transfer,
   3009                as that's the only alternative that is allowable. */
   3010             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   3011             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
   3012          }
   3013          return;
   3014       }
   3015 
   3016       /* Case: assisted transfer to arbitrary address */
   3017       switch (stmt->Ist.Exit.jk) {
   3018          /* Keep this list in sync with that in iselNext below */
   3019          case Ijk_ClientReq:
   3020          case Ijk_EmFail:
   3021          case Ijk_EmWarn:
   3022          case Ijk_NoDecode:
   3023          case Ijk_NoRedir:
   3024          case Ijk_SigBUS:
   3025          case Ijk_SigTRAP:
   3026          case Ijk_Sys_syscall:
   3027          case Ijk_TInval:
   3028          {
   3029             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   3030             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
   3031                                              stmt->Ist.Exit.jk));
   3032             return;
   3033          }
   3034          default:
   3035             break;
   3036       }
   3037 
   3038       /* Do we ever expect to see any other kind? */
   3039       goto stmt_fail;
   3040    }
   3041 
   3042    default:
   3043       break;
   3044    }
   3045 
   3046    stmt_fail:
   3047       vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
   3048       ppIRStmt(stmt);
   3049       vpanic("iselStmt:\n");
   3050 }
   3051 
   3052 /*---------------------------------------------------------*/
   3053 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   3054 /*---------------------------------------------------------*/
   3055 
   3056 static void iselNext ( ISelEnv* env,
   3057                        IRExpr* next, IRJumpKind jk, Int offsIP )
   3058 {
   3059    if (vex_traceflags & VEX_TRACE_VCODE) {
   3060       vex_printf( "\n-- PUT(%d) = ", offsIP);
   3061       ppIRExpr( next );
   3062       vex_printf( "; exit-");
   3063       ppIRJumpKind(jk);
   3064       vex_printf( "\n");
   3065    }
   3066 
   3067    /* Case: boring transfer to known address */
   3068    if (next->tag == Iex_Const) {
   3069       IRConst* cdst = next->Iex.Const.con;
   3070       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
   3071       if (jk == Ijk_Boring || jk == Ijk_Call) {
   3072          /* Boring transfer to known address */
   3073          MIPSAMode* amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
   3074          if (env->chainingAllowed) {
   3075             /* .. almost always true .. */
   3076             /* Skip the event check at the dst if this is a forwards
   3077                edge. */
   3078             Bool toFastEP
   3079                = env->mode64
   3080                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
   3081                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
   3082             if (0) vex_printf("%s", toFastEP ? "X" : ".");
   3083             addInstr(env, MIPSInstr_XDirect(
   3084                              env->mode64 ? (Addr64)cdst->Ico.U64
   3085                                          : (Addr64)cdst->Ico.U32,
   3086                              amPC, MIPScc_AL, toFastEP));
   3087          } else {
   3088             /* .. very occasionally .. */
   3089             /* We can't use chaining, so ask for an assisted transfer,
   3090                as that's the only alternative that is allowable. */
   3091             HReg r = iselWordExpr_R(env, next);
   3092             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
   3093                                               Ijk_Boring));
   3094          }
   3095          return;
   3096       }
   3097    }
   3098 
   3099    /* Case: call/return (==boring) transfer to any address */
   3100    switch (jk) {
   3101       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
   3102 
   3103          HReg       r     = iselWordExpr_R(env, next);
   3104          MIPSAMode*  amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
   3105          if (env->chainingAllowed) {
   3106             addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
   3107          } else {
   3108             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
   3109                                              Ijk_Boring));
   3110          }
   3111          return;
   3112       }
   3113       default:
   3114          break;
   3115    }
   3116 
   3117    /* Case: assisted transfer to arbitrary address */
   3118    switch (jk) {
   3119       /* Keep this list in sync with that for Ist_Exit above */
   3120       case Ijk_ClientReq:
   3121       case Ijk_EmFail:
   3122       case Ijk_EmWarn:
   3123       case Ijk_NoDecode:
   3124       case Ijk_NoRedir:
   3125       case Ijk_SigBUS:
   3126       case Ijk_SigTRAP:
   3127       case Ijk_Sys_syscall:
   3128       case Ijk_TInval: {
   3129          HReg      r     = iselWordExpr_R(env, next);
   3130          MIPSAMode* amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
   3131          addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
   3132          return;
   3133       }
   3134       default:
   3135          break;
   3136    }
   3137 
   3138    vex_printf( "\n-- PUT(%d) = ", offsIP);
   3139    ppIRExpr( next );
   3140    vex_printf( "; exit-");
   3141    ppIRJumpKind(jk);
   3142    vex_printf( "\n");
   3143    vassert(0); // are we expecting any other kind?
   3144 }
   3145 
   3146 /*---------------------------------------------------------*/
   3147 /*--- Insn selector top-level                           ---*/
   3148 /*---------------------------------------------------------*/
   3149 
   3150 /* Translate an entire BB to mips code. */
   3151 HInstrArray *iselSB_MIPS ( IRSB* bb,
   3152                            VexArch arch_host,
   3153                            VexArchInfo* archinfo_host,
   3154                            VexAbiInfo* vbi,
   3155                            Int offs_Host_EvC_Counter,
   3156                            Int offs_Host_EvC_FailAddr,
   3157                            Bool chainingAllowed,
   3158                            Bool addProfInc,
   3159                            Addr64 max_ga )
   3160 {
   3161    Int      i, j;
   3162    HReg     hreg, hregHI;
   3163    ISelEnv* env;
   3164    UInt     hwcaps_host = archinfo_host->hwcaps;
   3165    MIPSAMode *amCounter, *amFailAddr;
   3166 
   3167    /* sanity ... */
   3168    vassert(arch_host == VexArchMIPS32);
   3169    vassert(VEX_PRID_COMP_MIPS == hwcaps_host
   3170            || VEX_PRID_COMP_BROADCOM == hwcaps_host);
   3171 
   3172    mode64 = arch_host != VexArchMIPS32;
   3173 
   3174    /* Make up an initial environment to use. */
   3175    env = LibVEX_Alloc(sizeof(ISelEnv));
   3176    env->vreg_ctr = 0;
   3177    env->mode64 = mode64;
   3178 
   3179    /* Set up output code array. */
   3180    env->code = newHInstrArray();
   3181 
   3182    /* Copy BB's type env. */
   3183    env->type_env = bb->tyenv;
   3184 
   3185    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   3186       change as we go along. */
   3187    env->n_vregmap = bb->tyenv->types_used;
   3188    env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   3189    env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   3190 
   3191    /* and finally ... */
   3192    env->hwcaps          = hwcaps_host;
   3193    env->chainingAllowed = chainingAllowed;
   3194    env->hwcaps          = hwcaps_host;
   3195    env->max_ga          = max_ga;
   3196 
   3197    /* For each IR temporary, allocate a suitably-kinded virtual
   3198       register. */
   3199    j = 0;
   3200    for (i = 0; i < env->n_vregmap; i++) {
   3201       hregHI = hreg = INVALID_HREG;
   3202       switch (bb->tyenv->types[i]) {
   3203          case Ity_I1:
   3204          case Ity_I8:
   3205          case Ity_I16:
   3206          case Ity_I32: {
   3207             hreg = mkHReg(j++, HRcInt32, True);
   3208             break;
   3209          }
   3210          case Ity_I64: {
   3211             hreg = mkHReg(j++, HRcInt32, True);
   3212             hregHI = mkHReg(j++, HRcInt32, True);
   3213             break;
   3214          }
   3215          case Ity_I128:
   3216             vassert(mode64);
   3217             hreg = mkHReg(j++, HRcInt64, True);
   3218             hregHI = mkHReg(j++, HRcInt64, True);
   3219             break;
   3220          case Ity_F32: {
   3221             hreg = mkHReg(j++, HRcFlt32, True);
   3222             break;
   3223          }
   3224          case Ity_F64:
   3225             hreg = mkHReg(j++, HRcFlt64, True);
   3226             break;
   3227          default:
   3228             ppIRType(bb->tyenv->types[i]);
   3229             vpanic("iselBB(mips): IRTemp type");
   3230       }
   3231       env->vregmap[i] = hreg;
   3232       env->vregmapHI[i] = hregHI;
   3233    }
   3234    env->vreg_ctr = j;
   3235 
   3236    /* The very first instruction must be an event check. */
   3237    amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, hregMIPS_GPR10(mode64));
   3238    amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, hregMIPS_GPR10(mode64));
   3239    addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
   3240 
   3241    /* Possibly a block counter increment (for profiling).  At this
   3242       point we don't know the address of the counter, so just pretend
   3243       it is zero.  It will have to be patched later, but before this
   3244       translation is used, by a call to LibVEX_patchProfCtr. */
   3245    if (addProfInc) {
   3246       addInstr(env, MIPSInstr_ProfInc());
   3247    }
   3248 
   3249    /* Ok, finally we can iterate over the statements. */
   3250    for (i = 0; i < bb->stmts_used; i++)
   3251       iselStmt(env, bb->stmts[i]);
   3252 
   3253    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
   3254 
   3255    /* record the number of vregs we used. */
   3256    env->code->n_vregs = env->vreg_ctr;
   3257    return env->code;
   3258 
   3259 }
   3260 
   3261 /*---------------------------------------------------------------*/
   3262 /*--- end                                    host_mips_isel.c ---*/
   3263 /*---------------------------------------------------------------*/
   3264