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-2013 RT-RK
     11       mips-valgrind (at) rt-rk.com
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 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_generic_simd64.h"  /* for 64-bit SIMD helpers */
     39 #include "host_mips_defs.h"
     40 
     41 /*---------------------------------------------------------*/
     42 /*--- Register Usage Conventions                        ---*/
     43 /*---------------------------------------------------------*/
     44 
     45 /* Integer Regs
     46    ------------
     47    ZERO0       Reserved
     48    GPR12:22    Allocateable
     49    23          GuestStatePointer
     50    SP          StackFramePointer
     51    RA          LinkRegister */
     52 
     53 static Bool mode64 = False;
     54 
     55 /* Host CPU has FPU and 32 dbl. prec. FP registers. */
     56 static Bool fp_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 /* guest_COND offset */
     65 #define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
     66 
     67 /*---------------------------------------------------------*/
     68 /*--- ISelEnv                                           ---*/
     69 /*---------------------------------------------------------*/
     70 
     71 /* This carries around:
     72 
     73    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
     74      might encounter.  This is computed before insn selection starts,
     75      and does not change.
     76 
     77    - A mapping from IRTemp to HReg.  This tells the insn selector
     78      which virtual register(s) are associated with each IRTemp
     79      temporary.  This is computed before insn selection starts, and
     80      does not change.  We expect this mapping to map precisely the
     81      same set of IRTemps as the type mapping does.
     82 
     83         - vregmap   holds the primary register for the IRTemp.
     84         - vregmapHI is only used for 64-bit integer-typed
     85              IRTemps.  It holds the identity of a second
     86              32-bit virtual HReg, which holds the high half
     87              of the value.
     88 
     89    - The code array, that is, the insns selected so far.
     90 
     91    - A counter, for generating new virtual registers.
     92 
     93    - The host subarchitecture we are selecting insns for.
     94      This is set at the start and does not change.
     95 
     96    - A Bool for indicating whether we may generate chain-me
     97      instructions for control flow transfers, or whether we must use
     98      XAssisted.
     99 
    100    - The maximum guest address of any guest insn in this block.
    101      Actually, the address of the highest-addressed byte from any insn
    102      in this block.  Is set at the start and does not change.  This is
    103      used for detecting jumps which are definitely forward-edges from
    104      this block, and therefore can be made (chained) to the fast entry
    105      point of the destination, thereby avoiding the destination's
    106      event check.
    107 
    108    Note, this is all (well, mostly) host-independent.
    109 */
    110 
    111 typedef
    112    struct {
    113       /* Constant -- are set at the start and do not change. */
    114       IRTypeEnv*   type_env;
    115 
    116       HReg*        vregmap;
    117       HReg*        vregmapHI;
    118       Int          n_vregmap;
    119 
    120       UInt         hwcaps;
    121       Bool         mode64;
    122       Bool         fp_mode64;
    123 
    124       Bool         chainingAllowed;
    125       Addr64       max_ga;
    126 
    127       /* These are modified as we go along. */
    128       HInstrArray* code;
    129       Int          vreg_ctr;
    130    }
    131    ISelEnv;
    132 
    133 static HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
    134 {
    135    vassert(tmp >= 0);
    136    vassert(tmp < env->n_vregmap);
    137    return env->vregmap[tmp];
    138 }
    139 
    140 static void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
    141 {
    142    vassert(tmp >= 0);
    143    vassert(tmp < env->n_vregmap);
    144    vassert(! hregIsInvalid(env->vregmapHI[tmp]));
    145    *vrLO = env->vregmap[tmp];
    146    *vrHI = env->vregmapHI[tmp];
    147 }
    148 
    149 static void
    150 lookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
    151 {
    152    vassert(env->mode64);
    153    vassert(tmp >= 0);
    154    vassert(tmp < env->n_vregmap);
    155    vassert(! hregIsInvalid(env->vregmapHI[tmp]));
    156    *vrLO = env->vregmap[tmp];
    157    *vrHI = env->vregmapHI[tmp];
    158 }
    159 
    160 static void addInstr(ISelEnv * env, MIPSInstr * instr)
    161 {
    162    addHInstr(env->code, instr);
    163    if (vex_traceflags & VEX_TRACE_VCODE) {
    164       ppMIPSInstr(instr, mode64);
    165       vex_printf("\n");
    166    }
    167 }
    168 
    169 static HReg newVRegI(ISelEnv * env)
    170 {
    171    HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
    172                      True /*virtual reg */ );
    173    env->vreg_ctr++;
    174    return reg;
    175 }
    176 
    177 static HReg newVRegD(ISelEnv * env)
    178 {
    179    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /*virtual reg */ );
    180    env->vreg_ctr++;
    181    return reg;
    182 }
    183 
    184 static HReg newVRegF(ISelEnv * env)
    185 {
    186    HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->fp_mode64),
    187                      True /*virtual reg */ );
    188    env->vreg_ctr++;
    189    return reg;
    190 }
    191 
    192 static void add_to_sp(ISelEnv * env, UInt n)
    193 {
    194    HReg sp = StackPointer(mode64);
    195    vassert(n < 256 && (n % 8) == 0);
    196    if (mode64)
    197       addInstr(env, MIPSInstr_Alu(Malu_DADD, sp, sp, MIPSRH_Imm(True,
    198                                                                 toUShort(n))));
    199    else
    200       addInstr(env, MIPSInstr_Alu(Malu_ADD, sp, sp, MIPSRH_Imm(True,
    201                                                                toUShort(n))));
    202 }
    203 
    204 static void sub_from_sp(ISelEnv * env, UInt n)
    205 {
    206    HReg sp = StackPointer(mode64);
    207    vassert(n < 256 && (n % 8) == 0);
    208    if (mode64)
    209       addInstr(env, MIPSInstr_Alu(Malu_DSUB, sp, sp,
    210                                   MIPSRH_Imm(True, toUShort(n))));
    211    else
    212       addInstr(env, MIPSInstr_Alu(Malu_SUB, sp, sp,
    213                                   MIPSRH_Imm(True, toUShort(n))));
    214 }
    215 
    216 /*---------------------------------------------------------*/
    217 /*--- ISEL: Forward declarations                        ---*/
    218 /*---------------------------------------------------------*/
    219 
    220 /* These are organised as iselXXX and iselXXX_wrk pairs.  The
    221    iselXXX_wrk do the real work, but are not to be called directly.
    222    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
    223    checks that all returned registers are virtual.  You should not
    224    call the _wrk version directly.
    225 */
    226 /* 32-bit mode: Compute an I8/I16/I32 into a RH
    227                 (reg-or-halfword-immediate).
    228    It's important to specify whether the immediate is to be regarded
    229    as signed or not.  If yes, this will never return -32768 as an
    230    immediate; this guaranteed that all signed immediates that are
    231    return can have their sign inverted if need be.
    232 */
    233 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
    234 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
    235 
    236 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
    237    immediate in the range 1 .. 31 inclusive.  Used for doing shift amounts. */
    238 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
    239 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
    240 
    241 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
    242    immediate in the range 1 .. 63 inclusive.  Used for doing shift amounts. */
    243 static MIPSRH *iselWordExpr_RH6u_wrk(ISelEnv * env, IRExpr * e);
    244 static MIPSRH *iselWordExpr_RH6u(ISelEnv * env, IRExpr * e);
    245 
    246 /* compute an I8/I16/I32 into a GPR*/
    247 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e);
    248 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e);
    249 
    250 /* compute an I32 into an AMode. */
    251 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
    252                                          IRType xferTy);
    253 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy);
    254 
    255 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
    256                               IRExpr * e);
    257 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
    258 
    259 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
    260 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo,
    261                                ISelEnv * env, IRExpr * e);
    262 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
    263 
    264 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
    265 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
    266 
    267 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
    268 static HReg iselDblExpr(ISelEnv * env, IRExpr * e);
    269 
    270 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
    271 static HReg iselFltExpr(ISelEnv * env, IRExpr * e);
    272 
    273 static void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
    274 {
    275    /*
    276       rounding mode | MIPS | IR
    277       ------------------------
    278       to nearest    | 00  | 00
    279       to zero       | 01  | 11
    280       to +infinity  | 10  | 10
    281       to -infinity  | 11  | 01
    282     */
    283    /* rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 2 */
    284    HReg irrm = iselWordExpr_R(env, mode);
    285    HReg tmp = newVRegI(env);
    286    HReg fcsr_old = newVRegI(env);
    287    MIPSAMode *am_addr;
    288 
    289    addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
    290                                 MIPSRH_Imm(False, 1)));
    291    addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
    292    addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp, MIPSRH_Imm(False, 3)));
    293    /* save old value of FCSR */
    294    addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
    295    sub_from_sp(env, 8); /*  Move SP down 8 bytes */
    296    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
    297 
    298    /* store old FCSR to stack */
    299    addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
    300 
    301    /* set new value of FCSR */
    302    addInstr(env, MIPSInstr_MtFCSR(irrm));
    303 }
    304 
    305 static void set_MIPS_rounding_default(ISelEnv * env)
    306 {
    307    HReg fcsr = newVRegI(env);
    308    /* load as float */
    309    MIPSAMode *am_addr;
    310    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
    311 
    312    addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
    313 
    314    add_to_sp(env, 8);  /* Reset SP */
    315 
    316    /* set new value of FCSR*/
    317    addInstr(env, MIPSInstr_MtFCSR(fcsr));
    318 }
    319 
    320 /*---------------------------------------------------------*/
    321 /*--- ISEL: Misc helpers                                ---*/
    322 /*---------------------------------------------------------*/
    323 
    324 /* Make an int reg-reg move. */
    325 static MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
    326 {
    327    vassert(hregClass(r_dst) == hregClass(r_src));
    328    vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
    329    return MIPSInstr_Alu(Malu_OR, r_dst, r_src, MIPSRH_Reg(r_src));
    330 }
    331 
    332 /*---------------------------------------------------------*/
    333 /*--- ISEL: Function call helpers                       ---*/
    334 /*---------------------------------------------------------*/
    335 
    336 /* Used only in doHelperCall.  See big comment in doHelperCall re
    337    handling of register-parameter args.  This function figures out
    338    whether evaluation of an expression might require use of a fixed
    339    register.  If in doubt return True (safe but suboptimal).
    340 */
    341 static Bool mightRequireFixedRegs(IRExpr * e)
    342 {
    343    switch (e->tag) {
    344       case Iex_RdTmp:
    345       case Iex_Const:
    346       case Iex_Get:
    347          return False;
    348       default:
    349          return True;
    350    }
    351 }
    352 
    353 /* Load 2*I32 regs to fp reg */
    354 static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
    355 {
    356    HReg fr_dst = newVRegD(env);
    357    MIPSAMode *am_addr0, *am_addr1;
    358 
    359    vassert(hregClass(r_srcHi) == HRcInt32);
    360    vassert(hregClass(r_srcLo) == HRcInt32);
    361 
    362    sub_from_sp(env, 16);  /* Move SP down 16 bytes */
    363    am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
    364    am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
    365 
    366    /* store hi,lo as Ity_I32's */
    367 #if defined (_MIPSEL)
    368    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
    369    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
    370 #elif defined (_MIPSEB)
    371    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64));
    372    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64));
    373 #else
    374    /* Stop gcc on other platforms complaining about am_addr1 being set
    375       but not used. */
    376    (void)am_addr1;
    377 #endif
    378 
    379    /* load as float */
    380    addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
    381 
    382    add_to_sp(env, 16);  /* Reset SP */
    383    return fr_dst;
    384 }
    385 
    386 /* Do a complete function call.  |guard| is a Ity_Bit expression
    387    indicating whether or not the call happens.  If guard==NULL, the
    388    call is unconditional.  |retloc| is set to indicate where the
    389    return value is after the call.  The caller (of this fn) must
    390    generate code to add |stackAdjustAfterCall| to the stack pointer
    391    after the call is done. */
    392 
    393 static void doHelperCall(/*OUT*/UInt*   stackAdjustAfterCall,
    394                          /*OUT*/RetLoc* retloc,
    395                          ISelEnv* env,
    396                          IRExpr* guard,
    397                          IRCallee* cee, IRType retTy, IRExpr** args )
    398 {
    399    MIPSCondCode cc;
    400    HReg argregs[MIPS_N_REGPARMS];
    401    HReg tmpregs[MIPS_N_REGPARMS];
    402    Bool go_fast;
    403    Int n_args, i, argreg;
    404    UInt argiregs;
    405    HReg src = INVALID_HREG;
    406 
    407    /* Set default returns.  We'll update them later if needed. */
    408    *stackAdjustAfterCall = 0;
    409    *retloc               = mk_RetLoc_INVALID();
    410 
    411    /* These are used for cross-checking that IR-level constraints on
    412       the use of IRExpr_VECRET() and IRExpr_BBPTR() are observed. */
    413    UInt nVECRETs = 0;
    414    UInt nBBPTRs  = 0;
    415 
    416    /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
    417       are allowed to be used for passing integer arguments. They correspond
    418       to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
    419       on MIPS host (since we only implement one calling convention) and so we
    420       always ignore it. */
    421 
    422    /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
    423       are allowed to be used for passing integer arguments. They correspond
    424       to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
    425       on MIPS host (since we only implement one calling convention) and so we
    426       always ignore it. */
    427 
    428    /* The return type can be I{64,32,16,8} or V{128,256}.  In the
    429       latter two cases, it is expected that |args| will contain the
    430       special node IRExpr_VECRET(), in which case this routine
    431       generates code to allocate space on the stack for the vector
    432       return value.  Since we are not passing any scalars on the
    433       stack, it is enough to preallocate the return space before
    434       marshalling any arguments, in this case.
    435 
    436       |args| may also contain IRExpr_BBPTR(), in which case the value
    437       in the guest state pointer register is passed as the
    438       corresponding argument. */
    439 
    440    n_args = 0;
    441    for (i = 0; args[i]; i++) {
    442       IRExpr* arg = args[i];
    443       if (UNLIKELY(arg->tag == Iex_VECRET)) {
    444          nVECRETs++;
    445       } else if (UNLIKELY(arg->tag == Iex_BBPTR)) {
    446          nBBPTRs++;
    447       }
    448       n_args++;
    449    }
    450 
    451    if (n_args > MIPS_N_REGPARMS) {
    452       vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
    453    }
    454    if (mode64) {
    455       argregs[0] = hregMIPS_GPR4(mode64);
    456       argregs[1] = hregMIPS_GPR5(mode64);
    457       argregs[2] = hregMIPS_GPR6(mode64);
    458       argregs[3] = hregMIPS_GPR7(mode64);
    459       argregs[4] = hregMIPS_GPR8(mode64);
    460       argregs[5] = hregMIPS_GPR9(mode64);
    461       argregs[6] = hregMIPS_GPR10(mode64);
    462       argregs[7] = hregMIPS_GPR11(mode64);
    463       argiregs = 0;
    464       tmpregs[0] = tmpregs[1] = tmpregs[2] =
    465       tmpregs[3] = tmpregs[4] = tmpregs[5] =
    466       tmpregs[6] = tmpregs[7] = INVALID_HREG;
    467    } else {
    468       argregs[0] = hregMIPS_GPR4(mode64);
    469       argregs[1] = hregMIPS_GPR5(mode64);
    470       argregs[2] = hregMIPS_GPR6(mode64);
    471       argregs[3] = hregMIPS_GPR7(mode64);
    472       argiregs = 0;
    473       tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
    474    }
    475 
    476    /* First decide which scheme (slow or fast) is to be used. First assume the
    477       fast scheme, and select slow if any contraindications (wow) appear. */
    478 
    479    go_fast = True;
    480 
    481    /* We'll need space on the stack for the return value.  Avoid
    482       possible complications with nested calls by using the slow
    483       scheme. */
    484    if (retTy == Ity_V128 || retTy == Ity_V256)
    485       go_fast = False;
    486 
    487    if (go_fast && guard) {
    488       if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    489           && guard->Iex.Const.con->Ico.U1 == True) {
    490          /* unconditional */
    491       } else {
    492          /* Not manifestly unconditional -- be conservative. */
    493          go_fast = False;
    494       }
    495    }
    496 
    497    if (go_fast) {
    498       for (i = 0; i < n_args; i++) {
    499          if (mightRequireFixedRegs(args[i])) {
    500             go_fast = False;
    501             break;
    502          }
    503       }
    504    }
    505 
    506    /* At this point the scheme to use has been established.  Generate
    507       code to get the arg values into the argument rregs. */
    508    if (go_fast) {
    509       /* FAST SCHEME */
    510       argreg = 0;
    511 
    512       for (i = 0; i < n_args; i++) {
    513          IRExpr* arg = args[i];
    514          vassert(argreg < MIPS_N_REGPARMS);
    515 
    516          IRType  aTy = Ity_INVALID;
    517          if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
    518             aTy = typeOfIRExpr(env->type_env, arg);
    519 
    520          if (aTy == Ity_I32 || mode64) {
    521             argiregs |= (1 << (argreg + 4));
    522             addInstr(env, mk_iMOVds_RR(argregs[argreg],
    523                                        iselWordExpr_R(env, arg)));
    524             argreg++;
    525          } else if (aTy == Ity_I64) {  /* Ity_I64 */
    526             if (argreg & 1) {
    527                argreg++;
    528                argiregs |= (1 << (argreg + 4));
    529             }
    530             HReg rHi, rLo;
    531             iselInt64Expr(&rHi, &rLo, env, arg);
    532             argiregs |= (1 << (argreg + 4));
    533             addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
    534             argiregs |= (1 << (argreg + 4));
    535             addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
    536             argreg++;
    537          } else if (arg->tag == Iex_BBPTR) {
    538             vassert(0);  // ATC
    539             addInstr(env, mk_iMOVds_RR(argregs[argreg],
    540                                        GuestStatePointer(mode64)));
    541             argreg++;
    542          } else if (arg->tag == Iex_VECRET) {
    543             // If this happens, it denotes ill-formed IR.
    544             vassert(0);
    545          }
    546       }
    547       /* Fast scheme only applies for unconditional calls.  Hence: */
    548       cc = MIPScc_AL;
    549    } else {
    550       /* SLOW SCHEME; move via temporaries */
    551       argreg = 0;
    552 
    553       for (i = 0; i < n_args; i++) {
    554          vassert(argreg < MIPS_N_REGPARMS);
    555          IRExpr* arg = args[i];
    556 
    557          IRType  aTy = Ity_INVALID;
    558          if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
    559             aTy  = typeOfIRExpr(env->type_env, arg);
    560 
    561          if (aTy == Ity_I32 || (mode64 && arg->tag != Iex_BBPTR)) {
    562             tmpregs[argreg] = iselWordExpr_R(env, arg);
    563             argreg++;
    564          } else if (aTy == Ity_I64) {  /* Ity_I64 */
    565             if (argreg & 1)
    566                argreg++;
    567             if (argreg + 1 >= MIPS_N_REGPARMS)
    568                vassert(0);  /* out of argregs */
    569             HReg raHi, raLo;
    570             iselInt64Expr(&raHi, &raLo, env, arg);
    571             tmpregs[argreg] = raLo;
    572             argreg++;
    573             tmpregs[argreg] = raHi;
    574             argreg++;
    575          } else if (arg->tag == Iex_BBPTR) {
    576             tmpregs[argreg] = GuestStatePointer(mode64);
    577             argreg++;
    578          }
    579          else if (arg->tag == Iex_VECRET) {
    580             // If this happens, it denotes ill-formed IR
    581             vassert(0);
    582          }
    583       }
    584 
    585       /* Now we can compute the condition.  We can't do it earlier
    586          because the argument computations could trash the condition
    587          codes.  Be a bit clever to handle the common case where the
    588          guard is 1:Bit. */
    589       cc = MIPScc_AL;
    590       if (guard) {
    591          if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    592              && guard->Iex.Const.con->Ico.U1 == True) {
    593             /* unconditional -- do nothing */
    594          } else {
    595             cc = iselCondCode(env, guard);
    596             src = iselWordExpr_R(env, guard);
    597          }
    598       }
    599       /* Move the args to their final destinations. */
    600       for (i = 0; i < argreg; i++) {
    601          if (hregIsInvalid(tmpregs[i]))  /* Skip invalid regs */
    602             continue;
    603          /* None of these insns, including any spill code that might
    604             be generated, may alter the condition codes. */
    605          argiregs |= (1 << (i + 4));
    606          addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
    607       }
    608    }
    609 
    610    /* Do final checks, set the return values, and generate the call
    611       instruction proper. */
    612    vassert(nBBPTRs == 0 || nBBPTRs == 1);
    613    vassert(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0);
    614    vassert(*stackAdjustAfterCall == 0);
    615    vassert(is_RetLoc_INVALID(*retloc));
    616    switch (retTy) {
    617       case Ity_INVALID:
    618          /* Function doesn't return a value. */
    619          *retloc = mk_RetLoc_simple(RLPri_None);
    620          break;
    621       case Ity_I64:
    622          *retloc = mk_RetLoc_simple(mode64 ? RLPri_Int : RLPri_2Int);
    623          break;
    624       case Ity_I32: case Ity_I16: case Ity_I8:
    625          *retloc = mk_RetLoc_simple(RLPri_Int);
    626          break;
    627       case Ity_V128:
    628          vassert(0); // ATC
    629          *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0);
    630          *stackAdjustAfterCall = 16;
    631          break;
    632       case Ity_V256:
    633          vassert(0); // ATC
    634          *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0);
    635          *stackAdjustAfterCall = 32;
    636          break;
    637       default:
    638          /* IR can denote other possible return types, but we don't
    639             handle those here. */
    640         vassert(0);
    641    }
    642 
    643    ULong target = mode64 ? Ptr_to_ULong(cee->addr) :
    644                            toUInt(Ptr_to_ULong(cee->addr));
    645 
    646    /* Finally, generate the call itself.  This needs the *retloc value
    647       set in the switch above, which is why it's at the end. */
    648    if (cc == MIPScc_AL)
    649       addInstr(env, MIPSInstr_CallAlways(cc, (Addr64)target, argiregs,
    650                                          *retloc));
    651    else
    652       addInstr(env, MIPSInstr_Call(cc, (Addr64)target, argiregs, src, *retloc));
    653 }
    654 
    655 /*---------------------------------------------------------*/
    656 /*--- ISEL: Integer expression auxiliaries              ---*/
    657 /*---------------------------------------------------------*/
    658 
    659 /* --------------------- AMODEs --------------------- */
    660 
    661 /* Return an AMode which computes the value of the specified
    662    expression, possibly also adding insns to the code list as a
    663    result.  The expression may only be a word-size one.
    664 */
    665 
    666 static Bool uInt_fits_in_16_bits(UInt u)
    667 {
    668    Int i = u & 0xFFFF;
    669    i <<= 16;
    670    i >>= 16;
    671    return toBool(u == (UInt) i);
    672 }
    673 
    674 static Bool uLong_fits_in_16_bits ( ULong u )
    675 {
    676    Long i = u & 0xFFFFULL;
    677    i <<= 48;
    678    i >>= 48;
    679    return toBool(u == (ULong) i);
    680 }
    681 
    682 static Bool uLong_is_4_aligned ( ULong u )
    683 {
    684    return toBool((u & 3ULL) == 0);
    685 }
    686 
    687 static Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
    688 {
    689    switch (am->tag) {
    690       case Mam_IR:
    691          return toBool(hregClass(am->Mam.IR.base) == HRcGPR(mode64) &&
    692                   hregIsVirtual(am->Mam.IR.base) &&
    693                   uInt_fits_in_16_bits(am->Mam.IR.index));
    694       case Mam_RR:
    695          return toBool(hregClass(am->Mam.RR.base) == HRcGPR(mode64) &&
    696                   hregIsVirtual(am->Mam.RR.base) &&
    697                   hregClass(am->Mam.RR.index) == HRcGPR(mode64) &&
    698                   hregIsVirtual(am->Mam.RR.index));
    699       default:
    700          vpanic("sane_AMode: unknown mips amode tag");
    701    }
    702 }
    703 
    704 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
    705 {
    706    MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
    707    vassert(sane_AMode(env, am));
    708    return am;
    709 }
    710 
    711 /* DO NOT CALL THIS DIRECTLY ! */
    712 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
    713                                          IRType xferTy)
    714 {
    715    IRType ty = typeOfIRExpr(env->type_env, e);
    716    if (env->mode64) {
    717       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
    718       vassert(ty == Ity_I64);
    719 
    720       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
    721       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64
    722           && e->Iex.Binop.arg2->tag == Iex_Const
    723           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
    724           && (aligned4imm ?
    725           uLong_is_4_aligned(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64) : True)
    726           && uLong_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
    727          return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
    728                                    iselWordExpr_R(env, e->Iex.Binop.arg1));
    729       }
    730 
    731       /* Add64(expr,expr) */
    732       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64) {
    733          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
    734          HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
    735          return MIPSAMode_RR(r_idx, r_base);
    736       }
    737    } else {
    738       vassert(ty == Ity_I32);
    739 
    740       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
    741       if (e->tag == Iex_Binop
    742           && e->Iex.Binop.op == Iop_Add32
    743           && e->Iex.Binop.arg2->tag == Iex_Const
    744           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
    745           && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con-> Ico.U32)) {
    746          return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
    747                               iselWordExpr_R(env, e->Iex.Binop.arg1));
    748       }
    749 
    750       /* Add32(expr,expr) */
    751       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) {
    752          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
    753          HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
    754 
    755          return MIPSAMode_RR(r_idx, r_base);
    756       }
    757    }
    758 
    759    /* Doesn't match anything in particular.  Generate it into
    760       a register and use that. */
    761    return MIPSAMode_IR(0, iselWordExpr_R(env, e));
    762 }
    763 
    764 /*---------------------------------------------------------*/
    765 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
    766 /*---------------------------------------------------------*/
    767 
    768 /* Select insns for an integer-typed expression, and add them to the
    769    code list.  Return a reg holding the result.  This reg will be a
    770    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
    771    want to modify it, ask for a new vreg, copy it in there, and modify
    772    the copy.  The register allocator will do its best to map both
    773    vregs to the same real register, so the copies will often disappear
    774    later in the game.
    775 
    776    This should handle expressions of 64, 32, 16 and 8-bit type.
    777    All results are returned in a (mode64 ? 64bit : 32bit) register.
    778    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
    779    are arbitrary, so you should mask or sign extend partial values
    780    if necessary.
    781 */
    782 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
    783 {
    784    HReg r = iselWordExpr_R_wrk(env, e);
    785    /* sanity checks ... */
    786 
    787    vassert(hregClass(r) == HRcGPR(env->mode64));
    788    vassert(hregIsVirtual(r));
    789    return r;
    790 }
    791 
    792 /* DO NOT CALL THIS DIRECTLY ! */
    793 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
    794 {
    795    UInt argiregs = 0;
    796    IRType ty = typeOfIRExpr(env->type_env, e);
    797    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1
    798            || ty == Ity_F32 || (ty == Ity_I64 && mode64)
    799            || (ty == Ity_I128 && mode64));
    800 
    801    switch (e->tag) {
    802       /* --------- TEMP --------- */
    803       case Iex_RdTmp:
    804          return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    805 
    806       /* --------- LOAD --------- */
    807       case Iex_Load: {
    808          HReg r_dst = newVRegI(env);
    809          MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
    810 
    811          if (e->Iex.Load.end != Iend_LE
    812              && e->Iex.Load.end != Iend_BE)
    813             goto irreducible;
    814 
    815          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
    816                                       r_dst, am_addr, mode64));
    817          return r_dst;
    818       }
    819 
    820       /* --------- BINARY OP --------- */
    821       case Iex_Binop: {
    822          MIPSAluOp aluOp;
    823          MIPSShftOp shftOp;
    824 
    825          /* Is it an addition or logical style op? */
    826          switch (e->Iex.Binop.op) {
    827             case Iop_Add8:
    828             case Iop_Add16:
    829             case Iop_Add32:
    830                aluOp = Malu_ADD;
    831                break;
    832 
    833             case Iop_Sub8:
    834             case Iop_Sub16:
    835             case Iop_Sub32:
    836                aluOp = Malu_SUB;
    837                break;
    838 
    839             case Iop_Sub64:
    840                aluOp = Malu_DSUB;
    841                break;
    842 
    843             case Iop_And8:
    844             case Iop_And16:
    845             case Iop_And32:
    846             case Iop_And64:
    847                aluOp = Malu_AND;
    848                break;
    849 
    850             case Iop_Or8:
    851             case Iop_Or16:
    852             case Iop_Or32:
    853             case Iop_Or64:
    854                aluOp = Malu_OR;
    855                break;
    856 
    857             case Iop_Xor8:
    858             case Iop_Xor16:
    859             case Iop_Xor32:
    860             case Iop_Xor64:
    861                aluOp = Malu_XOR;
    862                break;
    863 
    864             case Iop_Add64:
    865                aluOp = Malu_DADD;
    866                break;
    867 
    868             default:
    869                aluOp = Malu_INVALID;
    870                break;
    871          }
    872 
    873          /* For commutative ops we assume any literal
    874             values are on the second operand. */
    875          if (aluOp != Malu_INVALID) {
    876             HReg r_dst = newVRegI(env);
    877             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    878             MIPSRH *ri_srcR = NULL;
    879             /* get right arg into an RH, in the appropriate way */
    880             switch (aluOp) {
    881                case Malu_ADD:
    882                case Malu_SUB:
    883                case Malu_DADD:
    884                case Malu_DSUB:
    885                   ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
    886                                             e->Iex.Binop.arg2);
    887                   break;
    888                case Malu_AND:
    889                case Malu_OR:
    890                case Malu_XOR:
    891                   ri_srcR = iselWordExpr_RH(env, False /*unsigned */,
    892                                             e->Iex.Binop.arg2);
    893                   break;
    894                default:
    895                   vpanic("iselWordExpr_R_wrk-aluOp-arg2");
    896             }
    897             addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
    898             return r_dst;
    899          }
    900 
    901          /* a shift? */
    902          switch (e->Iex.Binop.op) {
    903             case Iop_Shl32:
    904             case Iop_Shl64:
    905                shftOp = Mshft_SLL;
    906                break;
    907             case Iop_Shr32:
    908             case Iop_Shr64:
    909                shftOp = Mshft_SRL;
    910                break;
    911             case Iop_Sar32:
    912             case Iop_Sar64:
    913                shftOp = Mshft_SRA;
    914                break;
    915             default:
    916                shftOp = Mshft_INVALID;
    917                break;
    918          }
    919 
    920          /* we assume any literal values are on the second operand. */
    921          if (shftOp != Mshft_INVALID) {
    922             HReg r_dst = newVRegI(env);
    923             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    924             MIPSRH *ri_srcR;
    925             if (mode64)
    926                ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
    927             else
    928                ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
    929 
    930             if (ty == Ity_I8) {
    931                vassert(0);
    932             } else if (ty == Ity_I32) {
    933                if (mode64 && (shftOp == Mshft_SRA || shftOp == Mshft_SRL)) {
    934                   HReg tmp = newVRegI(env);
    935                   HReg r_srcL_se = newVRegI(env);
    936                   /* SRA, SRAV, SRL, SRLV: On 64-bit processors, if GPR rt does
    937                      not contain a sign-extended 32-bit value (bits 63..31
    938                      equal), then the result of the operation is UNPREDICTABLE.
    939                      So we need to sign-extend r_srcL:
    940                      DSLLV tmp, r_srcL, 32
    941                      DSRAV r_srcL_se, tmp, 32
    942                   */
    943                   addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tmp,
    944                                                r_srcL, MIPSRH_Imm(False, 32)));
    945                   addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, r_srcL_se,
    946                                                tmp, MIPSRH_Imm(False, 32)));
    947                   /* And finally do the shift. */
    948                   addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
    949                                                r_dst, r_srcL_se, ri_srcR));
    950                } else
    951                   addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
    952                                                r_dst, r_srcL, ri_srcR));
    953             } else if (ty == Ity_I64) {
    954                vassert(mode64);
    955                addInstr(env, MIPSInstr_Shft(shftOp, False/*64bit shift */,
    956                                             r_dst, r_srcL, ri_srcR));
    957             } else
    958                goto irreducible;
    959             return r_dst;
    960          }
    961 
    962          /* Cmp*32*(x,y) ? */
    963          if (e->Iex.Binop.op == Iop_CmpEQ32
    964              || e->Iex.Binop.op == Iop_CmpEQ16
    965              || e->Iex.Binop.op == Iop_CmpNE32
    966              || e->Iex.Binop.op == Iop_CmpNE64
    967              || e->Iex.Binop.op == Iop_CmpLT32S
    968              || e->Iex.Binop.op == Iop_CmpLT32U
    969              || e->Iex.Binop.op == Iop_CmpLT64U
    970              || e->Iex.Binop.op == Iop_CmpLE32U
    971              || e->Iex.Binop.op == Iop_CmpLE32S
    972              || e->Iex.Binop.op == Iop_CmpLE64S
    973              || e->Iex.Binop.op == Iop_CmpLT64S
    974              || e->Iex.Binop.op == Iop_CmpEQ64) {
    975 
    976             Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
    977                          || e->Iex.Binop.op == Iop_CmpLE32S
    978                          || e->Iex.Binop.op == Iop_CmpLT64S
    979                          || e->Iex.Binop.op == Iop_CmpLE64S);
    980             Bool size32;
    981             HReg dst = newVRegI(env);
    982             HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
    983             HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
    984 
    985             MIPSCondCode cc;
    986 
    987             switch (e->Iex.Binop.op) {
    988                case Iop_CmpEQ32:
    989                   cc = MIPScc_EQ;
    990                   size32 = True;
    991                   break;
    992                case Iop_CmpEQ16:
    993                   cc = MIPScc_EQ;
    994                   size32 = True;
    995                   break;
    996                case Iop_CmpNE32:
    997                   cc = MIPScc_NE;
    998                   size32 = True;
    999                   break;
   1000                case Iop_CmpNE64:
   1001                   cc = MIPScc_NE;
   1002                   size32 = True;
   1003                   break;
   1004                case Iop_CmpLT32S:
   1005                   cc = MIPScc_LT;
   1006                   size32 = True;
   1007                   break;
   1008                case Iop_CmpLT32U:
   1009                   cc = MIPScc_LO;
   1010                   size32 = True;
   1011                   break;
   1012                case Iop_CmpLT64U:
   1013                   cc = MIPScc_LO;
   1014                   size32 = False;
   1015                   break;
   1016                case Iop_CmpLE32U:
   1017                   cc = MIPScc_LE;
   1018                   size32 = True;
   1019                   break;
   1020                case Iop_CmpLE32S:
   1021                   cc = MIPScc_LE;
   1022                   size32 = True;
   1023                   break;
   1024                case Iop_CmpLE64S:
   1025                   cc = MIPScc_LE;
   1026                   size32 = False;
   1027                   break;
   1028                case Iop_CmpLT64S:
   1029                   cc = MIPScc_LT;
   1030                   size32 = False;
   1031                   break;
   1032                case Iop_CmpEQ64:
   1033                   cc = MIPScc_EQ;
   1034                   size32 = False;
   1035                   break;
   1036                default:
   1037                   vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
   1038             }
   1039 
   1040             addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
   1041             return dst;
   1042          }
   1043 
   1044          if (e->Iex.Binop.op == Iop_Max32U) {
   1045             HReg tmp = newVRegI(env);
   1046             HReg r_dst = newVRegI(env);
   1047             HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1048             HReg argR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1049             MIPSRH *argRH = iselWordExpr_RH(env, False /*signed */ ,
   1050                                            e->Iex.Binop.arg2);
   1051             /* max (v0, s0)
   1052                ------------
   1053                slt v1, v0, s0
   1054                movn v0, s0, v1 */
   1055 
   1056             addInstr(env, MIPSInstr_Alu(Malu_SLT, tmp, argL, argRH));
   1057             addInstr(env, mk_iMOVds_RR(r_dst, argL));
   1058             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, argR, tmp));
   1059             return r_dst;
   1060          }
   1061 
   1062          if (e->Iex.Binop.op == Iop_Mul32 || e->Iex.Binop.op == Iop_Mul64) {
   1063             Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
   1064             HReg r_dst = newVRegI(env);
   1065             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1066             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1067             addInstr(env, MIPSInstr_Mul(False/*Unsigned or Signed */ ,
   1068                                        False /*widen */ ,
   1069                                        sz32 /*32bit or 64bit */,
   1070                                        r_dst, r_srcL, r_srcR));
   1071             return r_dst;
   1072          }
   1073 
   1074          if (e->Iex.Binop.op == Iop_MullU32 || e->Iex.Binop.op == Iop_MullS32) {
   1075             HReg r_dst = newVRegI(env);
   1076             HReg tHi = newVRegI(env);
   1077             HReg tLo = newVRegI(env);
   1078             HReg tLo_1 = newVRegI(env);
   1079             HReg tHi_1 = newVRegI(env);
   1080             HReg mask = newVRegI(env);
   1081 
   1082             Bool syned = toBool(e->Iex.Binop.op == Iop_MullS32);
   1083             Bool size = toBool(e->Iex.Binop.op == Iop_MullS32)
   1084                         || toBool(e->Iex.Binop.op == Iop_MullU32);
   1085             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1086             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1087             addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */ ,
   1088                                         True /*widen */ ,
   1089                                         size /*32bit or 64bit mul */ ,
   1090                                         r_dst, r_srcL, r_srcR));
   1091 
   1092             addInstr(env, MIPSInstr_Mfhi(tHi));
   1093             addInstr(env, MIPSInstr_Mflo(tLo));
   1094 
   1095             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1,
   1096                           tHi, MIPSRH_Imm(False, 32)));
   1097 
   1098             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
   1099             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1100                           MIPSRH_Reg(mask)));
   1101 
   1102             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1103                           MIPSRH_Reg(tLo_1)));
   1104 
   1105             return r_dst;
   1106          }
   1107 
   1108          if (e->Iex.Binop.op == Iop_CmpF64) {
   1109             HReg r_srcL, r_srcR;
   1110             if (mode64) {
   1111                r_srcL = iselFltExpr(env, e->Iex.Binop.arg1);
   1112                r_srcR = iselFltExpr(env, e->Iex.Binop.arg2);
   1113             } else {
   1114                r_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
   1115                r_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
   1116             }
   1117             HReg tmp = newVRegI(env);
   1118             HReg r_ccMIPS = newVRegI(env);
   1119             HReg r_ccIR = newVRegI(env);
   1120             HReg r_ccIR_b0 = newVRegI(env);
   1121             HReg r_ccIR_b2 = newVRegI(env);
   1122             HReg r_ccIR_b6 = newVRegI(env);
   1123 
   1124             /* Create in dst, the IRCmpF64Result encoded result. */
   1125             /* chech for EQ */
   1126             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ, tmp, r_srcL, r_srcR));
   1127             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccMIPS, tmp,
   1128                                          MIPSRH_Imm(False, 1)));
   1129             /* chech for UN */
   1130             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN, tmp, r_srcL, r_srcR));
   1131             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
   1132                                         MIPSRH_Reg(tmp)));
   1133             /* chech for LT */
   1134             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT, tmp, r_srcL, r_srcR));
   1135             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp,
   1136                                          tmp, MIPSRH_Imm(False, 2)));
   1137             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
   1138                                         MIPSRH_Reg(tmp)));
   1139             /* chech for GT */
   1140             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_NGT,
   1141                                               tmp, r_srcL, r_srcR));
   1142             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, tmp,
   1143                                          MIPSRH_Imm(False, 3)));
   1144 
   1145             addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
   1146             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
   1147                                         MIPSRH_Imm(False, 8)));
   1148             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
   1149                                         MIPSRH_Reg(tmp)));
   1150             /* Map compare result from MIPS to IR,
   1151                conforming to CmpF64 definition.
   1152                FP cmp result | MIPS | IR
   1153                --------------------------
   1154                UN            | 0x1 | 0x45
   1155                EQ            | 0x2 | 0x40
   1156                GT            | 0x4 | 0x00
   1157                LT            | 0x8 | 0x01
   1158              */
   1159 
   1160             /* r_ccIR_b0 = r_ccMIPS[0] | r_ccMIPS[3] */
   1161             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b0, r_ccMIPS,
   1162                           MIPSRH_Imm(False, 0x3)));
   1163             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b0, r_ccMIPS,
   1164                           MIPSRH_Reg(r_ccIR_b0)));
   1165             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b0, r_ccIR_b0,
   1166                           MIPSRH_Imm(False, 0x1)));
   1167 
   1168             /* r_ccIR_b2 = r_ccMIPS[0] */
   1169             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b2, r_ccMIPS,
   1170                           MIPSRH_Imm(False, 0x2)));
   1171             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b2, r_ccIR_b2,
   1172                           MIPSRH_Imm(False, 0x4)));
   1173 
   1174             /* r_ccIR_b6 = r_ccMIPS[0] | r_ccMIPS[1] */
   1175             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b6,
   1176                           r_ccMIPS, MIPSRH_Imm(False, 0x1)));
   1177             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b6, r_ccMIPS,
   1178                           MIPSRH_Reg(r_ccIR_b6)));
   1179             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b6, r_ccIR_b6,
   1180                           MIPSRH_Imm(False, 0x6)));
   1181             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b6, r_ccIR_b6,
   1182                           MIPSRH_Imm(False, 0x40)));
   1183 
   1184             /* r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 */
   1185             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR_b0,
   1186                           MIPSRH_Reg(r_ccIR_b2)));
   1187             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR,
   1188                           MIPSRH_Reg(r_ccIR_b6)));
   1189             return r_ccIR;
   1190          }
   1191 
   1192          if (e->Iex.Binop.op == Iop_DivModU64to32 ||
   1193              e->Iex.Binop.op == Iop_DivModS64to32) {
   1194             HReg tLo = newVRegI(env);
   1195             HReg tHi = newVRegI(env);
   1196             HReg mask = newVRegI(env);
   1197             HReg tLo_1 = newVRegI(env);
   1198             HReg tHi_1 = newVRegI(env);
   1199             HReg r_dst = newVRegI(env);
   1200             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
   1201 
   1202             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1203             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1204 
   1205             addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
   1206             addInstr(env, MIPSInstr_Mfhi(tHi));
   1207             addInstr(env, MIPSInstr_Mflo(tLo));
   1208 
   1209             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
   1210                                          MIPSRH_Imm(False, 32)));
   1211 
   1212             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
   1213             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1214                           MIPSRH_Reg(mask)));
   1215 
   1216             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1217                           MIPSRH_Reg(tLo_1)));
   1218 
   1219             return r_dst;
   1220          }
   1221 
   1222          if (e->Iex.Binop.op == Iop_8HLto16
   1223              || e->Iex.Binop.op == Iop_16HLto32) {
   1224             HReg tHi   = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1225             HReg tLo   = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1226             HReg tLo_1 = newVRegI(env);
   1227             HReg tHi_1 = newVRegI(env);
   1228             HReg r_dst = newVRegI(env);
   1229             UInt shift = 0;
   1230             UInt mask  = 0;
   1231             switch (e->Iex.Binop.op) {
   1232                case Iop_8HLto16:
   1233                   shift = 8;
   1234                   mask  = 0xff;
   1235                   break;
   1236                case Iop_16HLto32:
   1237                   shift = 16;
   1238                   mask  = 0xffff;
   1239                   break;
   1240                default:
   1241                   break;
   1242             }
   1243 
   1244             /* sll tHi_1, tHi,   shift
   1245                and tLo_1, tLo,   mask
   1246                or  r_dst, tHi_1, tLo_1 */
   1247             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tHi_1, tHi,
   1248                                          MIPSRH_Imm(False, shift)));
   1249             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1250                           MIPSRH_Imm(False, mask)));
   1251             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1252                           MIPSRH_Reg(tLo_1)));
   1253             return r_dst;
   1254          }
   1255 
   1256          if (e->Iex.Binop.op == Iop_32HLto64) {
   1257             vassert(mode64);
   1258             HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1259             HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1260             HReg tLo_1 = newVRegI(env);
   1261             HReg tHi_1 = newVRegI(env);
   1262             HReg r_dst = newVRegI(env);
   1263             HReg mask = newVRegI(env);
   1264 
   1265             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
   1266                                          MIPSRH_Imm(False, 32)));
   1267 
   1268             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
   1269             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
   1270                           MIPSRH_Reg(mask)));
   1271             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
   1272                           MIPSRH_Reg(tLo_1)));
   1273 
   1274             return r_dst;
   1275          }
   1276 
   1277          if (e->Iex.Binop.op == Iop_F32toI64S) {
   1278             vassert(mode64);
   1279             HReg valS = newVRegI(env);
   1280             HReg tmpF = newVRegF(env);
   1281             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
   1282 
   1283             /* CVTLS tmpF, valF */
   1284             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   1285             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpF, valF));
   1286             set_MIPS_rounding_default(env);
   1287 
   1288             /* Doubleword Move from Floating Point
   1289                dmfc1 valS, tmpF */
   1290             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
   1291 
   1292             return valS;
   1293          }
   1294 
   1295          if (e->Iex.Binop.op == Iop_F64toI32S) {
   1296             HReg valD;
   1297             if (mode64)
   1298                valD = iselFltExpr(env, e->Iex.Binop.arg2);
   1299             else
   1300                valD = iselDblExpr(env, e->Iex.Binop.arg2);
   1301             HReg valS = newVRegF(env);
   1302             HReg r_dst = newVRegI(env);
   1303 
   1304             /* CVTWD valS, valD */
   1305             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   1306             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
   1307             set_MIPS_rounding_default(env);
   1308 
   1309             /* Move Word From Floating Point
   1310                mfc1 r_dst, valS */
   1311             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
   1312 
   1313             return r_dst;
   1314          }
   1315 
   1316          /* -------- DSP ASE -------- */
   1317          /* All used cases involving host-side helper calls. */
   1318          void* fn = NULL;
   1319          switch (e->Iex.Binop.op) {
   1320             case Iop_HAdd8Ux4:
   1321                fn = &h_generic_calc_HAdd8Ux4; break;
   1322             case Iop_HSub8Ux4:
   1323                fn = &h_generic_calc_HSub8Ux4; break;
   1324             case Iop_HSub16Sx2:
   1325                fn = &h_generic_calc_HSub16Sx2; break;
   1326             case Iop_QSub8Ux4:
   1327                fn = &h_generic_calc_QSub8Ux4; break;
   1328             default:
   1329                   break;
   1330          }
   1331 
   1332          /* What's the retloc? */
   1333          RetLoc rloc = mk_RetLoc_INVALID();
   1334          if (ty == Ity_I32) {
   1335             rloc = mk_RetLoc_simple(RLPri_Int);
   1336          }
   1337          else if (ty == Ity_I64) {
   1338             rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
   1339                             mk_RetLoc_simple(RLPri_2Int);
   1340          }
   1341          else {
   1342             goto irreducible;
   1343          }
   1344 
   1345          if (fn) {
   1346             HReg regL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1347             HReg regR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1348             HReg res  = newVRegI(env);
   1349             addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
   1350             addInstr(env, mk_iMOVds_RR(hregMIPS_GPR5(env->mode64), regR));
   1351             argiregs |= (1 << 4);
   1352             argiregs |= (1 << 5);
   1353             addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
   1354                                                 (HWord)Ptr_to_ULong(fn),
   1355                                                 argiregs, rloc));
   1356             addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
   1357             return res;
   1358          }
   1359       break;
   1360    }
   1361 
   1362    /* --------- UNARY OP --------- */
   1363    case Iex_Unop: {
   1364       IROp op_unop = e->Iex.Unop.op;
   1365 
   1366       switch (op_unop) {
   1367          case Iop_1Sto8:
   1368          case Iop_1Sto16:
   1369          case Iop_1Sto32:
   1370          case Iop_8Sto16:
   1371          case Iop_8Sto32:
   1372          case Iop_16Sto32:
   1373          case Iop_16Sto64:
   1374          case Iop_8Sto64:
   1375          case Iop_1Sto64: {
   1376             HReg r_dst = newVRegI(env);
   1377             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1378             Bool sz32;
   1379             UShort amt;
   1380             switch (op_unop) {
   1381                case Iop_1Sto8:
   1382                   amt = 31;
   1383                   sz32 = True;
   1384                   break;
   1385                case Iop_1Sto16:
   1386                   amt = 31;
   1387                   sz32 = True;
   1388                   break;
   1389                case Iop_1Sto32:
   1390                   amt = 31;
   1391                   sz32 = True;
   1392                   break;
   1393                case Iop_16Sto32:
   1394                   amt = 16;
   1395                   sz32 = True;
   1396                   break;
   1397                case Iop_16Sto64:
   1398                   amt = 48;
   1399                   sz32 = False;
   1400                   break;
   1401                case Iop_8Sto16:
   1402                   amt = 24;
   1403                   sz32 = True;
   1404                   break;
   1405                case Iop_8Sto32:
   1406                   amt = 24;
   1407                   sz32 = True;
   1408                   break;
   1409                case Iop_8Sto64:
   1410                   amt = 56;
   1411                   sz32 = False;
   1412                   break;
   1413                case Iop_1Sto64:
   1414                   amt = 63;
   1415                   sz32 = False;
   1416                   break;
   1417                default:
   1418                   vassert(0);
   1419             }
   1420 
   1421             addInstr(env, MIPSInstr_Shft(Mshft_SLL, sz32, r_dst, r_src,
   1422                                          MIPSRH_Imm(False, amt)));
   1423             addInstr(env, MIPSInstr_Shft(Mshft_SRA, sz32, r_dst, r_dst,
   1424                                          MIPSRH_Imm(False, amt)));
   1425             return r_dst;
   1426          }
   1427 
   1428          /* not(x) = nor(x,x) */
   1429          case Iop_Not1: {
   1430             HReg r_dst = newVRegI(env);
   1431             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1432             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   1433 
   1434             addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   1435             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
   1436             return r_dst;
   1437          }
   1438 
   1439          case Iop_Not8:
   1440          case Iop_Not16:
   1441          case Iop_Not32:
   1442          case Iop_Not64: {
   1443             HReg r_dst = newVRegI(env);
   1444             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1445             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   1446 
   1447             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
   1448             return r_dst;
   1449          }
   1450 
   1451          case Iop_ReinterpF32asI32: {
   1452             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
   1453             HReg r_dst = newVRegI(env);
   1454 
   1455             /* Move Word From Floating Point
   1456                mfc1 r_dst, fr_src */
   1457             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, fr_src));
   1458 
   1459             return r_dst;
   1460          }
   1461 
   1462          case Iop_ReinterpF64asI64: {
   1463             vassert(mode64);
   1464             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
   1465             HReg r_dst = newVRegI(env);
   1466 
   1467             /* Doubleword Move from Floating Point
   1468                mfc1 r_dst, fr_src */
   1469             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, r_dst, fr_src));
   1470 
   1471             return r_dst;
   1472          }
   1473 
   1474          case Iop_F64toI32S: {
   1475             HReg valD;
   1476             if (mode64)
   1477                valD = iselFltExpr(env, e->Iex.Binop.arg2);
   1478             else
   1479                valD = iselDblExpr(env, e->Iex.Binop.arg2);
   1480             HReg valS = newVRegF(env);
   1481             HReg r_dst = newVRegI(env);
   1482 
   1483             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   1484             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
   1485             set_MIPS_rounding_default(env);
   1486 
   1487             /* Move Word From Floating Point
   1488                mfc1 r_dst, valS */
   1489             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
   1490 
   1491             return r_dst;
   1492          }
   1493 
   1494          case Iop_16to8:
   1495          case Iop_32to1:
   1496          case Iop_32to8:
   1497          case Iop_32to16:
   1498             return iselWordExpr_R(env, e->Iex.Unop.arg);
   1499 
   1500          case Iop_32HIto16: {
   1501             HReg r_dst = newVRegI(env);
   1502             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1503             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   1504                                          r_dst, r_src, MIPSRH_Imm(False, 16)));
   1505             return r_dst;
   1506          }
   1507 
   1508          case Iop_64to1:
   1509          case Iop_64to8: {
   1510             vassert(mode64);
   1511             HReg r_src, r_dst;
   1512             UShort mask = (op_unop == Iop_64to1) ? 0x1 : 0xFF;
   1513             r_dst = newVRegI(env);
   1514             r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1515             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
   1516                           MIPSRH_Imm(False, mask)));
   1517             return r_dst;
   1518          }
   1519 
   1520          case Iop_16HIto8: {
   1521             HReg r_dst = newVRegI(env);
   1522             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1523             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   1524                                          r_dst, r_src, MIPSRH_Imm(False, 8)));
   1525             return r_dst;
   1526          }
   1527 
   1528          case Iop_1Uto8:
   1529          case Iop_1Uto32:
   1530          case Iop_1Uto64:
   1531          case Iop_8Uto16:
   1532          case Iop_8Uto32:
   1533          case Iop_8Uto64:
   1534          case Iop_16Uto32:
   1535          case Iop_16Uto64: {
   1536             HReg r_dst = newVRegI(env);
   1537             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1538             UShort mask = 0;
   1539             switch (op_unop) {
   1540                case Iop_1Uto64:
   1541                   vassert(mode64);
   1542                case Iop_1Uto8:
   1543                case Iop_1Uto32:
   1544                   mask = toUShort(0x1);
   1545                   break;
   1546                case Iop_8Uto64:
   1547                   vassert(mode64);
   1548                case Iop_8Uto16:
   1549                case Iop_8Uto32:
   1550                   mask = toUShort(0xFF);
   1551                   break;
   1552                case Iop_16Uto64:
   1553                   vassert(mode64);
   1554                case Iop_16Uto32:
   1555                   mask = toUShort(0xFFFF);
   1556                   break;
   1557                default:
   1558                   vassert(0);
   1559                   break;
   1560             }
   1561             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
   1562                           MIPSRH_Imm(False, mask)));
   1563             return r_dst;
   1564          }
   1565 
   1566          case Iop_32Uto64: {
   1567             HReg r_dst = newVRegI(env);
   1568             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1569             vassert(mode64);
   1570             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False /*!32bit shift */,
   1571                                          r_dst, r_src, MIPSRH_Imm(False, 32)));
   1572             addInstr(env, MIPSInstr_Shft(Mshft_SRL, False /*!32bit shift */,
   1573                                          r_dst, r_dst, MIPSRH_Imm(False, 32)));
   1574             return r_dst;
   1575          }
   1576 
   1577          case Iop_64HIto32: {
   1578             if (env->mode64) {
   1579                HReg r_dst = newVRegI(env);
   1580                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1581                addInstr(env, MIPSInstr_Shft(Mshft_SRA, False /*64bit shift */,
   1582                        r_dst, r_src, MIPSRH_Imm(True, 32)));
   1583                return r_dst;
   1584             } else {
   1585                HReg rHi, rLo;
   1586                iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1587                return rHi;
   1588             }
   1589          }
   1590 
   1591          case Iop_64to32: {
   1592             if (env->mode64) {
   1593                HReg r_dst = newVRegI(env);
   1594                r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
   1595                return r_dst;
   1596             } else {
   1597                HReg rHi, rLo;
   1598                iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1599                return rLo;
   1600             }
   1601          }
   1602 
   1603          case Iop_64to16: {
   1604             vassert(env->mode64);
   1605             HReg r_dst = newVRegI(env);
   1606             r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
   1607             return r_dst;
   1608          }
   1609 
   1610          case Iop_32Sto64: {
   1611             HReg r_dst = newVRegI(env);
   1612             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1613             vassert(mode64);
   1614             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*!32bit shift */,
   1615                                          r_dst, r_src, MIPSRH_Imm(True, 0)));
   1616             return r_dst;
   1617          }
   1618 
   1619          case Iop_CmpNEZ8:
   1620          case Iop_CmpNEZ16: {
   1621             HReg r_dst = newVRegI(env);
   1622             HReg tmp = newVRegI(env);
   1623             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1624             UShort mask = (op_unop == Iop_CmpNEZ8) ? 0xFF : 0xFFFF;
   1625 
   1626             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
   1627                                         MIPSRH_Imm(False, mask)));
   1628             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
   1629                                         hregMIPS_GPR0(mode64), MIPScc_NE));
   1630             return r_dst;
   1631          }
   1632 
   1633          case Iop_CmpNEZ32: {
   1634             HReg r_dst = newVRegI(env);
   1635             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1636 
   1637             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
   1638                                         hregMIPS_GPR0(mode64), MIPScc_NE));
   1639             return r_dst;
   1640          }
   1641 
   1642          case Iop_CmpwNEZ32: {
   1643             HReg r_dst = newVRegI(env);
   1644             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1645 
   1646             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
   1647                           MIPSRH_Reg(r_src)));
   1648 
   1649             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
   1650                                         MIPSRH_Reg(r_src)));
   1651             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
   1652                                          MIPSRH_Imm(False, 31)));
   1653             return r_dst;
   1654          }
   1655 
   1656          case Iop_Left8:
   1657          case Iop_Left16:
   1658          case Iop_Left32:
   1659          case Iop_Left64: {
   1660             if (op_unop == Iop_Left64 && !mode64)
   1661                goto irreducible;
   1662             HReg r_dst = newVRegI(env);
   1663             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1664             MIPSAluOp op = (op_unop == Iop_Left64) ? Malu_DSUB : Malu_SUB;
   1665             addInstr(env, MIPSInstr_Alu(op, r_dst,
   1666                                         hregMIPS_GPR0(mode64),
   1667                                         MIPSRH_Reg(r_src)));
   1668             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
   1669                           MIPSRH_Reg(r_src)));
   1670             return r_dst;
   1671          }
   1672 
   1673          case Iop_Clz64:
   1674             vassert(mode64);
   1675          case Iop_Clz32: {
   1676             HReg r_dst = newVRegI(env);
   1677             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1678             MIPSUnaryOp op = (op_unop == Iop_Clz64) ? Mun_DCLZ : Mun_CLZ;
   1679             addInstr(env, MIPSInstr_Unary(op, r_dst, r_src));
   1680             return r_dst;
   1681          }
   1682 
   1683          case Iop_CmpNEZ64: {
   1684             HReg hi, lo;
   1685             HReg r_dst = newVRegI(env);
   1686             HReg r_src;
   1687             if (env->mode64) {
   1688                r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   1689             } else {
   1690                r_src = newVRegI(env);
   1691                iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
   1692                addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
   1693             }
   1694             addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
   1695                                         hregMIPS_GPR0(mode64), MIPScc_NE));
   1696             return r_dst;
   1697          }
   1698 
   1699          case Iop_CmpwNEZ64: {
   1700             HReg tmp1;
   1701             HReg tmp2 = newVRegI(env);
   1702             vassert(env->mode64);
   1703             tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
   1704 
   1705             addInstr(env, MIPSInstr_Alu(Malu_DSUB, tmp2, hregMIPS_GPR0(mode64),
   1706                           MIPSRH_Reg(tmp1)));
   1707 
   1708             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
   1709             addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
   1710                                          MIPSRH_Imm (False, 63)));
   1711             return tmp2;
   1712          }
   1713 
   1714          case Iop_128HIto64: {
   1715             vassert(mode64);
   1716             HReg rHi, rLo;
   1717             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1718             return rHi;  /* and abandon rLo .. poor wee thing :-) */
   1719          }
   1720 
   1721          case Iop_128to64: {
   1722             vassert(mode64);
   1723             HReg rHi, rLo;
   1724             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
   1725             return rLo;  /* and abandon rLo .. poor wee thing :-) */
   1726          }
   1727 
   1728          default:
   1729             break;
   1730       }
   1731 
   1732       /* -------- DSP ASE -------- */
   1733       /* All Unop cases involving host-side helper calls. */
   1734       void* fn = NULL;
   1735       switch (e->Iex.Unop.op) {
   1736          case Iop_CmpNEZ16x2:
   1737             fn = &h_generic_calc_CmpNEZ16x2; break;
   1738          case Iop_CmpNEZ8x4:
   1739             fn = &h_generic_calc_CmpNEZ8x4; break;
   1740          default:
   1741             break;
   1742       }
   1743 
   1744       RetLoc rloc = mk_RetLoc_INVALID();
   1745       if (ty == Ity_I32) {
   1746          rloc = mk_RetLoc_simple(RLPri_Int);
   1747       }
   1748       else if (ty == Ity_I64) {
   1749          rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
   1750                          mk_RetLoc_simple(RLPri_2Int);
   1751       }
   1752       else {
   1753          goto irreducible;
   1754       }
   1755 
   1756       if (fn) {
   1757          HReg regL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1758          HReg res  = newVRegI(env);
   1759          addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
   1760          argiregs |= (1 << 4);
   1761          addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
   1762                                              (HWord)Ptr_to_ULong(fn),
   1763                                              argiregs, rloc));
   1764          addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
   1765          return res;
   1766       }
   1767 
   1768       break;
   1769    }
   1770 
   1771    /* --------- GET --------- */
   1772    case Iex_Get: {
   1773       if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
   1774           || ((ty == Ity_I64) && mode64)) {
   1775          HReg r_dst = newVRegI(env);
   1776 
   1777          MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   1778                                            GuestStatePointer(mode64));
   1779          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
   1780                                       mode64));
   1781          return r_dst;
   1782       }
   1783       break;
   1784    }
   1785 
   1786    /* --------- ITE --------- */
   1787    case Iex_ITE: {
   1788       if ((ty == Ity_I8 || ty == Ity_I16 ||
   1789            ty == Ity_I32 || ((ty == Ity_I64))) &&
   1790            typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
   1791          HReg r_dst  = iselWordExpr_R(env, e->Iex.ITE.iffalse);
   1792          HReg r1     = iselWordExpr_R(env, e->Iex.ITE.iftrue);
   1793          HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
   1794          /*
   1795           * r_dst = r0
   1796           * movn r_dst, r1, r_cond
   1797           */
   1798          addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, r1, r_cond));
   1799          return r_dst;
   1800       }
   1801       break;
   1802    }
   1803 
   1804    /* --------- LITERAL --------- */
   1805    /* 32/16/8-bit literals */
   1806    case Iex_Const: {
   1807       Long l;
   1808       HReg r_dst = newVRegI(env);
   1809       IRConst *con = e->Iex.Const.con;
   1810       switch (con->tag) {
   1811          case Ico_U64:
   1812             if (!mode64)
   1813                goto irreducible;
   1814             l = (Long) con->Ico.U64;
   1815             break;
   1816          case Ico_U32:
   1817             l = (Long) (Int) con->Ico.U32;
   1818             break;
   1819          case Ico_U16:
   1820             l = (Long) (Int) (Short) con->Ico.U16;
   1821             break;
   1822          case Ico_U8:
   1823             l = (Long) (Int) (Char) con->Ico.U8;
   1824             break;
   1825          default:
   1826             vpanic("iselIntExpr_R.const(mips)");
   1827       }
   1828       addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
   1829       return r_dst;
   1830    }
   1831 
   1832    /* --------- CCALL --------- */
   1833    case Iex_CCall: {
   1834       HReg r_dst = newVRegI(env);
   1835       vassert(ty == e->Iex.CCall.retty);
   1836 
   1837       /* be very restrictive for now.  Only 32/64-bit ints allowed for
   1838          args, and 64 and 32 bits for return type.  Don't forget to change
   1839          the RetLoc if more return types are allowed in future. */
   1840       if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32)
   1841          goto irreducible;
   1842 
   1843       /* Marshal args, do the call, clear stack. */
   1844       UInt   addToSp = 0;
   1845       RetLoc rloc    = mk_RetLoc_INVALID();
   1846       doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
   1847                    e->Iex.CCall.retty, e->Iex.CCall.args );
   1848 
   1849       vassert(is_sane_RetLoc(rloc));
   1850       vassert(rloc.pri == RLPri_Int);
   1851       vassert(addToSp == 0);
   1852       addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
   1853       return r_dst;
   1854    }
   1855 
   1856    default:
   1857       break;
   1858    }  /* end switch(e->tag) */
   1859 
   1860    /* We get here if no pattern matched. */
   1861    irreducible:
   1862       vex_printf("--------------->\n");
   1863       if (e->tag == Iex_RdTmp)
   1864          vex_printf("Iex_RdTmp \n");
   1865       ppIRExpr(e);
   1866 
   1867       vpanic("iselWordExpr_R(mips): cannot reduce tree");
   1868 }
   1869 
   1870 /* --------------------- RH --------------------- */
   1871 
   1872 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
   1873    (reg-or-halfword-immediate).  It's important to specify whether the
   1874    immediate is to be regarded as signed or not.  If yes, this will
   1875    never return -32768 as an immediate; this guaranteed that all
   1876    signed immediates that are return can have their sign inverted if
   1877    need be. */
   1878 
   1879 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
   1880 {
   1881    MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
   1882    /* sanity checks ... */
   1883    switch (ri->tag) {
   1884       case Mrh_Imm:
   1885          vassert(ri->Mrh.Imm.syned == syned);
   1886          if (syned)
   1887             vassert(ri->Mrh.Imm.imm16 != 0x8000);
   1888          return ri;
   1889       case Mrh_Reg:
   1890          vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
   1891          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
   1892          return ri;
   1893       default:
   1894          vpanic("iselIntExpr_RH: unknown mips RH tag");
   1895    }
   1896 }
   1897 
   1898 /* DO NOT CALL THIS DIRECTLY ! */
   1899 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
   1900 {
   1901    ULong u;
   1902    Long l;
   1903    IRType ty = typeOfIRExpr(env->type_env, e);
   1904    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1905           ((ty == Ity_I64) && env->mode64));
   1906 
   1907    /* special case: immediate */
   1908    if (e->tag == Iex_Const) {
   1909       IRConst *con = e->Iex.Const.con;
   1910       /* What value are we aiming to generate? */
   1911       switch (con->tag) {
   1912          /* Note: Not sign-extending - we carry 'syned' around */
   1913          case Ico_U64:
   1914             vassert(env->mode64);
   1915             u = con->Ico.U64;
   1916             break;
   1917          case Ico_U32:
   1918             u = 0xFFFFFFFF & con->Ico.U32;
   1919             break;
   1920          case Ico_U16:
   1921             u = 0x0000FFFF & con->Ico.U16;
   1922             break;
   1923          case Ico_U8:
   1924             u = 0x000000FF & con->Ico.U8;
   1925             break;
   1926          default:
   1927             vpanic("iselIntExpr_RH.Iex_Const(mips)");
   1928       }
   1929       l = (Long) u;
   1930       /* Now figure out if it's representable. */
   1931       if (!syned && u <= 65535) {
   1932          return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
   1933       }
   1934       if (syned && l >= -32767 && l <= 32767) {
   1935          return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
   1936       }
   1937       /* no luck; use the Slow Way. */
   1938    }
   1939    /* default case: calculate into a register and return that */
   1940    return MIPSRH_Reg(iselWordExpr_R(env, e));
   1941 }
   1942 
   1943 /* --------------------- RH5u --------------------- */
   1944 
   1945 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
   1946    being an immediate in the range 1 .. 31 inclusive.  Used for doing
   1947    shift amounts. */
   1948 
   1949 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
   1950 {
   1951    MIPSRH *ri;
   1952    ri = iselWordExpr_RH5u_wrk(env, e);
   1953    /* sanity checks ... */
   1954    switch (ri->tag) {
   1955       case Mrh_Imm:
   1956          vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
   1957          vassert(!ri->Mrh.Imm.syned);
   1958          return ri;
   1959       case Mrh_Reg:
   1960          vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
   1961          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
   1962          return ri;
   1963       default:
   1964          vpanic("iselIntExpr_RH5u: unknown mips RH tag");
   1965    }
   1966 }
   1967 
   1968 /* DO NOT CALL THIS DIRECTLY ! */
   1969 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
   1970 {
   1971    IRType ty = typeOfIRExpr(env->type_env, e);
   1972    vassert(ty == Ity_I8);
   1973 
   1974    /* special case: immediate */
   1975    if (e->tag == Iex_Const
   1976        && e->Iex.Const.con->tag == Ico_U8
   1977        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
   1978       return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
   1979    }
   1980 
   1981    /* default case: calculate into a register and return that */
   1982    return MIPSRH_Reg(iselWordExpr_R(env, e));
   1983 }
   1984 
   1985 /* --------------------- RH6u --------------------- */
   1986 
   1987 /* Only used in 64-bit mode. */
   1988 static MIPSRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
   1989 {
   1990    MIPSRH *ri;
   1991    ri = iselWordExpr_RH6u_wrk(env, e);
   1992    /* sanity checks ... */
   1993    switch (ri->tag) {
   1994    case Mrh_Imm:
   1995       vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 63);
   1996       vassert(!ri->Mrh.Imm.syned);
   1997       return ri;
   1998    case Mrh_Reg:
   1999       vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
   2000       vassert(hregIsVirtual(ri->Mrh.Reg.reg));
   2001       return ri;
   2002    default:
   2003       vpanic("iselIntExpr_RH6u: unknown mips64 RI tag");
   2004    }
   2005 }
   2006 
   2007 /* DO NOT CALL THIS DIRECTLY ! */
   2008 static MIPSRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
   2009 {
   2010    IRType ty = typeOfIRExpr(env->type_env, e);
   2011    vassert(ty == Ity_I8);
   2012 
   2013    /* special case: immediate */
   2014    if (e->tag == Iex_Const
   2015        && e->Iex.Const.con->tag == Ico_U8
   2016        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
   2017    {
   2018       return MIPSRH_Imm(False /*unsigned */ ,
   2019               e->Iex.Const.con->Ico.U8);
   2020    }
   2021 
   2022    /* default case: calculate into a register and return that */
   2023    return MIPSRH_Reg(iselWordExpr_R(env, e));
   2024 }
   2025 
   2026 /* --------------------- CONDCODE --------------------- */
   2027 
   2028 /* Generate code to evaluated a bit-typed expression, returning the
   2029    condition code which would correspond when the expression would
   2030    notionally have returned 1. */
   2031 
   2032 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
   2033 {
   2034    MIPSCondCode cc = iselCondCode_wrk(env,e);
   2035    vassert(cc != MIPScc_NV);
   2036    return cc;
   2037 }
   2038 
   2039 /* DO NOT CALL THIS DIRECTLY ! */
   2040 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
   2041 {
   2042    vassert(e);
   2043    vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
   2044    /* Cmp*32*(x,y) ? */
   2045    if (e->Iex.Binop.op == Iop_CmpEQ32
   2046        || e->Iex.Binop.op == Iop_CmpNE32
   2047        || e->Iex.Binop.op == Iop_CmpNE64
   2048        || e->Iex.Binop.op == Iop_CmpLT32S
   2049        || e->Iex.Binop.op == Iop_CmpLT32U
   2050        || e->Iex.Binop.op == Iop_CmpLT64U
   2051        || e->Iex.Binop.op == Iop_CmpLE32S
   2052        || e->Iex.Binop.op == Iop_CmpLE64S
   2053        || e->Iex.Binop.op == Iop_CmpLT64S
   2054        || e->Iex.Binop.op == Iop_CmpEQ64) {
   2055 
   2056       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
   2057                    || e->Iex.Binop.op == Iop_CmpLE32S
   2058                    || e->Iex.Binop.op == Iop_CmpLT64S
   2059                    || e->Iex.Binop.op == Iop_CmpLE64S);
   2060       Bool size32;
   2061       HReg dst = newVRegI(env);
   2062       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2063       HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2064 
   2065       MIPSCondCode cc;
   2066 
   2067       switch (e->Iex.Binop.op) {
   2068          case Iop_CmpEQ32:
   2069             cc = MIPScc_EQ;
   2070             size32 = True;
   2071             break;
   2072          case Iop_CmpNE32:
   2073             cc = MIPScc_NE;
   2074             size32 = True;
   2075             break;
   2076          case Iop_CmpNE64:
   2077             cc = MIPScc_NE;
   2078             size32 = True;
   2079             break;
   2080          case Iop_CmpLT32S:
   2081             cc = MIPScc_LT;
   2082             size32 = True;
   2083             break;
   2084          case Iop_CmpLT32U:
   2085             cc = MIPScc_LO;
   2086             size32 = True;
   2087             break;
   2088          case Iop_CmpLT64U:
   2089             cc = MIPScc_LO;
   2090             size32 = False;
   2091             break;
   2092          case Iop_CmpLE32S:
   2093             cc = MIPScc_LE;
   2094             size32 = True;
   2095             break;
   2096          case Iop_CmpLE64S:
   2097             cc = MIPScc_LE;
   2098             size32 = False;
   2099             break;
   2100          case Iop_CmpLT64S:
   2101             cc = MIPScc_LT;
   2102             size32 = False;
   2103             break;
   2104          case Iop_CmpEQ64:
   2105             cc = MIPScc_EQ;
   2106             size32 = False;
   2107             break;
   2108          default:
   2109             vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
   2110             break;
   2111       }
   2112 
   2113       addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
   2114       /* Store result to guest_COND */
   2115       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   2116 
   2117       addInstr(env, MIPSInstr_Store(4,
   2118                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
   2119                             am_addr->Mam.IR.base),
   2120                dst, mode64));
   2121       return cc;
   2122    }
   2123    if (e->Iex.Binop.op == Iop_Not1) {
   2124       HReg r_dst = newVRegI(env);
   2125       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   2126       MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
   2127 
   2128       addInstr(env, MIPSInstr_LI(r_dst, 0x1));
   2129       addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
   2130       /* Store result to guest_COND */
   2131       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   2132 
   2133       addInstr(env, MIPSInstr_Store(4,
   2134                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
   2135                             am_addr->Mam.IR.base),
   2136                r_dst, mode64));
   2137       return MIPScc_NE;
   2138    }
   2139    if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
   2140       HReg r_dst = iselWordExpr_R_wrk(env, e);
   2141       /* Store result to guest_COND */
   2142       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
   2143 
   2144       addInstr(env, MIPSInstr_Store(4,
   2145                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
   2146                             am_addr->Mam.IR.base),
   2147                r_dst, mode64));
   2148       return MIPScc_EQ;
   2149    }
   2150 
   2151    vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
   2152    ppIRExpr(e);
   2153    vpanic("iselCondCode(mips)");
   2154 }
   2155 
   2156 /*---------------------------------------------------------*/
   2157 /*--- ISEL: Integer expressions (128 bit)               ---*/
   2158 /*---------------------------------------------------------*/
   2159 
   2160 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
   2161    which is returned as the first two parameters.  As with
   2162    iselWordExpr_R, these may be either real or virtual regs; in any
   2163    case they must not be changed by subsequent code emitted by the
   2164    caller.  */
   2165 
   2166 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   2167 {
   2168    vassert(env->mode64);
   2169    iselInt128Expr_wrk(rHi, rLo, env, e);
   2170    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
   2171    vassert(hregIsVirtual(*rHi));
   2172    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
   2173    vassert(hregIsVirtual(*rLo));
   2174 }
   2175 
   2176 /* DO NOT CALL THIS DIRECTLY ! */
   2177 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
   2178                                IRExpr * e)
   2179 {
   2180    vassert(e);
   2181    vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
   2182 
   2183    /* read 128-bit IRTemp */
   2184    if (e->tag == Iex_RdTmp) {
   2185       lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
   2186       return;
   2187    }
   2188 
   2189    /* --------- BINARY ops --------- */
   2190    if (e->tag == Iex_Binop) {
   2191       switch (e->Iex.Binop.op) {
   2192          /* 64 x 64 -> 128 multiply */
   2193          case Iop_MullU64:
   2194          case Iop_MullS64: {
   2195             HReg tLo = newVRegI(env);
   2196             HReg tHi = newVRegI(env);
   2197             Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
   2198             HReg r_dst = newVRegI(env);
   2199             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2200             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2201             addInstr(env, MIPSInstr_Mul(syned, True, False /*64bit mul */ ,
   2202                                         r_dst, r_srcL, r_srcR));
   2203             addInstr(env, MIPSInstr_Mfhi(tHi));
   2204             addInstr(env, MIPSInstr_Mflo(tLo));
   2205             *rHi = tHi;
   2206             *rLo = tLo;
   2207             return;
   2208          }
   2209 
   2210          /* 64HLto128(e1,e2) */
   2211          case Iop_64HLto128:
   2212             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2213             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2214             return;
   2215 
   2216          case Iop_DivModS64to64: {
   2217             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2218             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2219             HReg tLo = newVRegI(env);
   2220             HReg tHi = newVRegI(env);
   2221             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
   2222 
   2223             addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
   2224             addInstr(env, MIPSInstr_Mfhi(tHi));
   2225             addInstr(env, MIPSInstr_Mflo(tLo));
   2226             *rHi = tHi;
   2227             *rLo = tLo;
   2228             return;
   2229          }
   2230 
   2231          case Iop_DivModU128to64:
   2232          case Iop_DivModS128to64: {
   2233             vassert(mode64);
   2234             HReg rHi1, rLo1;
   2235             iselInt128Expr(&rHi1, &rLo1, env, e->Iex.Binop.arg1);
   2236 
   2237             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2238             HReg tLo = newVRegI(env);
   2239             HReg tHi = newVRegI(env);
   2240             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS128to64);
   2241 
   2242             addInstr(env, MIPSInstr_Div(syned, False, rLo1, r_srcR));
   2243             addInstr(env, MIPSInstr_Mfhi(tHi));
   2244             addInstr(env, MIPSInstr_Mflo(tLo));
   2245             *rHi = tHi;
   2246             *rLo = tLo;
   2247             return;
   2248          }
   2249 
   2250          default:
   2251             break;
   2252       }
   2253    }
   2254    vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
   2255    ppIRExpr(e);
   2256    vpanic("iselInt128Expr(mips64)");
   2257 }
   2258 
   2259 /*---------------------------------------------------------*/
   2260 /*--- ISEL: Integer expressions (64 bit)                ---*/
   2261 /*---------------------------------------------------------*/
   2262 
   2263 /* 32-bit mode ONLY. Compute a 64-bit value into the register
   2264  * pair HI, LO. HI and LO must not be changed by subsequent
   2265  *  code emitted by the caller. */
   2266 
   2267 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   2268 {
   2269    vassert(!env->mode64);
   2270    iselInt64Expr_wrk(rHi, rLo, env, e);
   2271    vassert(hregClass(*rHi) == HRcInt32);
   2272    vassert(hregIsVirtual(*rHi));
   2273    vassert(hregClass(*rLo) == HRcInt32);
   2274    vassert(hregIsVirtual(*rLo));
   2275 }
   2276 
   2277 /* DO NOT CALL THIS DIRECTLY ! */
   2278 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
   2279 {
   2280    vassert(e);
   2281    vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
   2282 
   2283    /* read 64-bit IRTemp */
   2284    if (e->tag == Iex_RdTmp) {
   2285       lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
   2286       return;
   2287    }
   2288    /* 64-bit load */
   2289    if (e->tag == Iex_Load) {
   2290       HReg tLo = newVRegI(env);
   2291       HReg tHi = newVRegI(env);
   2292       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
   2293       addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
   2294       addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
   2295       *rHi = tHi;
   2296       *rLo = tLo;
   2297       return;
   2298    }
   2299 
   2300    /* 64-bit literal */
   2301    if (e->tag == Iex_Const) {
   2302       ULong w64 = e->Iex.Const.con->Ico.U64;
   2303       UInt wHi = toUInt(w64 >> 32);
   2304       UInt wLo = toUInt(w64);
   2305       HReg tLo = newVRegI(env);
   2306       HReg tHi = newVRegI(env);
   2307       vassert(e->Iex.Const.con->tag == Ico_U64);
   2308 
   2309       if (wLo == wHi) {
   2310          /* Save a precious Int register in this special case. */
   2311          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
   2312          *rHi = tLo;
   2313          *rLo = tLo;
   2314       } else {
   2315          addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
   2316          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
   2317          *rHi = tHi;
   2318          *rLo = tLo;
   2319       }
   2320 
   2321       return;
   2322    }
   2323 
   2324    /* 64-bit GET */
   2325    if (e->tag == Iex_Get) {
   2326       HReg tLo = newVRegI(env);
   2327       HReg tHi = newVRegI(env);
   2328 
   2329       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   2330                                         GuestStatePointer(mode64));
   2331       addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
   2332       addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
   2333       *rHi = tHi;
   2334       *rLo = tLo;
   2335       return;
   2336    }
   2337 
   2338    /* 64-bit ITE */
   2339    if (e->tag == Iex_ITE) {
   2340       vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
   2341       HReg expr0Lo, expr0Hi;
   2342       HReg expr1Lo, expr1Hi;
   2343       HReg desLo  = newVRegI(env);
   2344       HReg desHi  = newVRegI(env);
   2345       HReg cond = iselWordExpr_R(env, e->Iex.ITE.cond);
   2346 
   2347       /* expr0Hi:expr0Lo = iffalse */
   2348       /* expr1Hi:expr1Lo = iftrue */
   2349       iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.ITE.iffalse);
   2350       iselInt64Expr(&expr1Hi, &expr1Lo, env, e->Iex.ITE.iftrue);
   2351 
   2352       /* move desLo, expr0Lo
   2353        * move desHi, expr0Hi
   2354        * movn desLo, expr1Lo, cond
   2355        * movn desHi, expr1Hi, cond */
   2356       addInstr(env, mk_iMOVds_RR(desLo, expr0Lo));
   2357       addInstr(env, mk_iMOVds_RR(desHi, expr0Hi));
   2358       addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desLo, expr1Lo, cond));
   2359       addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desHi, expr1Hi, cond));
   2360 
   2361       *rHi = desHi;
   2362       *rLo = desLo;
   2363       return;
   2364    }
   2365 
   2366    /* --------- BINARY ops --------- */
   2367    if (e->tag == Iex_Binop) {
   2368       IROp op_binop = e->Iex.Binop.op;
   2369       switch (op_binop) {
   2370          /* 32 x 32 -> 64 multiply */
   2371          /* Add64 */
   2372          case Iop_Add64: {
   2373             HReg xLo, xHi, yLo, yHi, carryBit;
   2374 
   2375             HReg tHi = newVRegI(env);
   2376             HReg tHi1 = newVRegI(env);
   2377             HReg tLo = newVRegI(env);
   2378 
   2379             carryBit = newVRegI(env);
   2380 
   2381             Bool size32 = True;
   2382             MIPSCondCode cc = MIPScc_LO;
   2383 
   2384             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
   2385             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
   2386             addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
   2387 
   2388             /* Check carry. */
   2389             addInstr(env, MIPSInstr_Cmp(False, size32, carryBit, tLo, xLo, cc));
   2390 
   2391             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi1, xHi, MIPSRH_Reg(yHi)));
   2392             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, tHi1,
   2393                                         MIPSRH_Reg(carryBit)));
   2394 
   2395             *rHi = tHi;
   2396             *rLo = tLo;
   2397             return;
   2398          }
   2399          case Iop_Sub64: {
   2400             HReg xLo, xHi, yLo, yHi, borrow;
   2401             Bool size32 = True;
   2402             MIPSCondCode cc = MIPScc_LO;
   2403 
   2404             HReg tHi = newVRegI(env);
   2405             HReg tLo = newVRegI(env);
   2406 
   2407             borrow = newVRegI(env);
   2408 
   2409             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
   2410             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
   2411 
   2412             addInstr(env, MIPSInstr_Alu(Malu_SUB, tLo, xLo, MIPSRH_Reg(yLo)));
   2413 
   2414             /* Check if borrow is nedded. */
   2415             addInstr(env, MIPSInstr_Cmp(False, size32, borrow, xLo, yLo, cc));
   2416 
   2417             addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi,
   2418                                         MIPSRH_Reg(borrow)));
   2419             addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, xHi, MIPSRH_Reg(yHi)));
   2420 
   2421             *rHi = tHi;
   2422             *rLo = tLo;
   2423             return;
   2424          }
   2425          case Iop_MullU32:
   2426          case Iop_MullS32: {
   2427             HReg tLo = newVRegI(env);
   2428             HReg tHi = newVRegI(env);
   2429             HReg r_dst = newVRegI(env);
   2430             Bool syned = toBool(op_binop == Iop_MullS32);
   2431             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2432             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2433 
   2434             addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */,
   2435                                         True /*widen */ , True,
   2436                                         r_dst, r_srcL, r_srcR));
   2437             addInstr(env, MIPSInstr_Mfhi(tHi));
   2438             addInstr(env, MIPSInstr_Mflo(tLo));
   2439             *rHi = tHi;
   2440             *rLo = tLo;
   2441 
   2442             return;
   2443          }
   2444          case Iop_DivModS64to32:
   2445          case Iop_DivModU64to32: {
   2446             HReg r_sHi, r_sLo;
   2447             HReg tLo = newVRegI(env);
   2448             HReg tHi = newVRegI(env);
   2449             Bool syned = toBool(op_binop == Iop_DivModS64to32);
   2450             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2451 
   2452             iselInt64Expr(&r_sHi, &r_sLo, env, e->Iex.Binop.arg1);
   2453             addInstr(env, MIPSInstr_Div(syned, True, r_sLo, r_srcR));
   2454             addInstr(env, MIPSInstr_Mfhi(tHi));
   2455             addInstr(env, MIPSInstr_Mflo(tLo));
   2456             *rHi = tHi;
   2457             *rLo = tLo;
   2458 
   2459             return;
   2460          }
   2461 
   2462          /* 32HLto64(e1,e2) */
   2463          case Iop_32HLto64:
   2464             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
   2465             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
   2466 
   2467             return;
   2468          /* Or64/And64/Xor64 */
   2469          case Iop_Or64:
   2470          case Iop_And64:
   2471          case Iop_Xor64: {
   2472             HReg xLo, xHi, yLo, yHi;
   2473             HReg tLo = newVRegI(env);
   2474             HReg tHi = newVRegI(env);
   2475             MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
   2476                            (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
   2477             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
   2478             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
   2479             addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
   2480             addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
   2481             *rHi = tHi;
   2482             *rLo = tLo;
   2483             return;
   2484          }
   2485 
   2486          case Iop_Shr64: {
   2487 #if defined (_MIPSEL)
   2488             /* 64-bit logical shift right based on what gcc generates:
   2489                <shift>:
   2490                nor  v0, zero, a2
   2491                sll  a3, a1, 0x1
   2492                sllv a3, a3, v0
   2493                srlv v0, a0, a2
   2494                srlv v1, a1, a2
   2495                andi a0, a2, 0x20
   2496                or   v0, a3, v0
   2497                movn v0, v1, a0
   2498                jr   ra
   2499                movn v1, zero, a0
   2500             */
   2501             HReg a0, a1;
   2502             HReg a0tmp = newVRegI(env);
   2503             HReg a2 = newVRegI(env);
   2504             HReg a3 = newVRegI(env);
   2505             HReg v0 = newVRegI(env);
   2506             HReg v1 = newVRegI(env);
   2507             HReg zero = newVRegI(env);
   2508             MIPSRH *sa = NULL;
   2509 
   2510             iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
   2511             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
   2512 
   2513             if (sa->tag == Mrh_Imm) {
   2514                addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
   2515             }
   2516             else {
   2517                addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
   2518                                            MIPSRH_Imm(False, 0x3f)));
   2519             }
   2520 
   2521             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
   2522             /* nor  v0, zero, a2 */
   2523             addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
   2524             /* sll  a3, a1, 0x1 */
   2525             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2526                                          a3, a1, MIPSRH_Imm(False, 0x1)));
   2527             /* sllv a3, a3, v0 */
   2528             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2529                                          a3, a3, MIPSRH_Reg(v0)));
   2530             /* srlv v0, a0, a2 */
   2531             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2532                                          v0, a0, MIPSRH_Reg(a2)));
   2533             /* srlv v1, a1, a2 */
   2534             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2535                                          v1, a1, MIPSRH_Reg(a2)));
   2536             /* andi a0, a2, 0x20 */
   2537             addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
   2538                                         MIPSRH_Imm(False, 0x20)));
   2539             /* or   v0, a3, v0 */
   2540             addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
   2541 
   2542             /* movn    v0, v1, a0 */
   2543             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
   2544             /* movn    v1, zero, a0 */
   2545             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, zero, a0tmp));
   2546 
   2547             *rHi = v1;
   2548             *rLo = v0;
   2549             return;
   2550 #elif defined (_MIPSEB)
   2551             /* 64-bit logical shift right based on what gcc generates:
   2552                <shift>:
   2553                nor  v0, zero, a2
   2554                sll  a3, a0, 0x1
   2555                sllv a3, a3, v0
   2556                srlv v1, a1, a2
   2557                andi v0, a2, 0x20
   2558                or   v1, a3, v1
   2559                srlv a2, a0, a2
   2560                movn v1, a2, v0
   2561                movn a2, zero, v0
   2562                jr   ra
   2563                move v0, a2
   2564             */
   2565             HReg a0, a1;
   2566             HReg a2 = newVRegI(env);
   2567             HReg a2tmp = newVRegI(env);
   2568             HReg a3 = newVRegI(env);
   2569             HReg v0 = newVRegI(env);
   2570             HReg v1 = newVRegI(env);
   2571             HReg zero = newVRegI(env);
   2572             MIPSRH *sa = NULL;
   2573 
   2574             iselInt64Expr(&a0, &a1, env, e->Iex.Binop.arg1);
   2575             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
   2576 
   2577             if (sa->tag == Mrh_Imm) {
   2578                addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
   2579             }
   2580             else {
   2581                addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
   2582                                            MIPSRH_Imm(False, 0x3f)));
   2583             }
   2584 
   2585             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
   2586             /* nor v0, zero, a2 */
   2587             addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
   2588             /* sll a3, a0, 0x1 */
   2589             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2590                                          a3, a0, MIPSRH_Imm(False, 0x1)));
   2591             /* sllv a3, a3, v0 */
   2592             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2593                                          a3, a3, MIPSRH_Reg(v0)));
   2594             /* srlv v1, a1, a2 */
   2595             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2596                                          v1, a1, MIPSRH_Reg(a2)));
   2597             /* andi v0, a2, 0x20 */
   2598             addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
   2599                                         MIPSRH_Imm(False, 0x20)));
   2600             /* or v1, a3, v1 */
   2601             addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
   2602             /* srlv a2, a0, a2 */
   2603             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2604                              a2tmp, a0, MIPSRH_Reg(a2)));
   2605 
   2606             /* movn v1, a2, v0 */
   2607             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2tmp, v0));
   2608             /* movn  a2, zero, v0 */
   2609             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2tmp, zero, v0));
   2610             /* move v0, a2 */
   2611             addInstr(env, mk_iMOVds_RR(v0, a2tmp));
   2612 
   2613             *rHi = v0;
   2614             *rLo = v1;
   2615             return;
   2616 #endif
   2617          }
   2618 
   2619          case Iop_Shl64: {
   2620             /* 64-bit shift left based on what gcc generates:
   2621                <shift>:
   2622                nor  v0,zero,a2
   2623                srl  a3,a0,0x1
   2624                srlv a3,a3,v0
   2625                sllv v1,a1,a2
   2626                andi v0,a2,0x20
   2627                or   v1,a3,v1
   2628                sllv a2,a0,a2
   2629                movn v1,a2,v0
   2630                movn a2,zero,v0
   2631                jr   ra
   2632                move v0,a2
   2633             */
   2634             HReg a0, a1;
   2635             HReg a2 = newVRegI(env);
   2636             HReg a3 = newVRegI(env);
   2637             HReg v0 = newVRegI(env);
   2638             HReg v1 = newVRegI(env);
   2639             HReg zero = newVRegI(env);
   2640             MIPSRH *sa = NULL;
   2641 
   2642             iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
   2643             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
   2644 
   2645             if (sa->tag == Mrh_Imm) {
   2646                addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
   2647             }
   2648             else {
   2649                addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
   2650                                            MIPSRH_Imm(False, 0x3f)));
   2651             }
   2652 
   2653             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
   2654             /* nor v0, zero, a2 */
   2655             addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
   2656             /* srl a3, a0, 0x1 */
   2657             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2658                                          a3, a0, MIPSRH_Imm(False, 0x1)));
   2659             /* srlv a3, a3, v0 */
   2660             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2661                                          a3, a3, MIPSRH_Reg(v0)));
   2662             /* sllv v1, a1, a2 */
   2663             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2664                                          v1, a1, MIPSRH_Reg(a2)));
   2665             /* andi v0, a2, 0x20 */
   2666             addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
   2667                                         MIPSRH_Imm(False, 0x20)));
   2668             /* or v1, a3, v1 */
   2669             addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
   2670             /* sllv a2, a0, a2 */
   2671             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2672                                          a2, a0, MIPSRH_Reg(a2)));
   2673 
   2674             /* movn v1, a2, v0 */
   2675             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2, v0));
   2676             /* movn a2, zero, v0 */
   2677             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2, zero, v0));
   2678             addInstr(env, mk_iMOVds_RR(v0, a2));
   2679 
   2680             *rHi = v1;
   2681             *rLo = v0;
   2682             return;
   2683          }
   2684 
   2685          case Iop_Sar64: {
   2686             /* 64-bit arithmetic shift right based on what gcc generates:
   2687                <shift>:
   2688                nor  v0, zero, a2
   2689                sll  a3, a1, 0x1
   2690                sllv a3, a3, v0
   2691                srlv v0, a0, a2
   2692                srav v1, a1, a2
   2693                andi a0, a2, 0x20
   2694                sra  a1, a1, 0x1f
   2695                or   v0, a3, v0
   2696                movn v0, v1, a0
   2697                jr   ra
   2698                movn v1, a1, a0
   2699             */
   2700             HReg a0, a1;
   2701             HReg a0tmp = newVRegI(env);
   2702             HReg a1tmp = newVRegI(env);
   2703             HReg a2 = newVRegI(env);
   2704             HReg a3 = newVRegI(env);
   2705             HReg v0 = newVRegI(env);
   2706             HReg v1 = newVRegI(env);
   2707             HReg zero = newVRegI(env);
   2708             MIPSRH *sa = NULL;
   2709 
   2710             iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
   2711             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
   2712 
   2713             if (sa->tag == Mrh_Imm) {
   2714                addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
   2715             }
   2716             else {
   2717                addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
   2718                                            MIPSRH_Imm(False, 0x3f)));
   2719             }
   2720 
   2721             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
   2722             /* nor  v0, zero, a2 */
   2723             addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
   2724             /* sll  a3, a1, 0x1 */
   2725             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2726                                          a3, a1, MIPSRH_Imm(False, 0x1)));
   2727             /* sllv a3, a3, v0 */
   2728             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
   2729                                          a3, a3, MIPSRH_Reg(v0)));
   2730             /* srlv v0, a0, a2 */
   2731             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
   2732                                          v0, a0, MIPSRH_Reg(a2)));
   2733             /* srav v1, a1, a2 */
   2734             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
   2735                                          v1, a1, MIPSRH_Reg(a2)));
   2736             /* andi a0, a2, 0x20 */
   2737             addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
   2738                                         MIPSRH_Imm(False, 0x20)));
   2739             /* sra a1, a1, 0x1f */
   2740             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
   2741                                          a1tmp, a1, MIPSRH_Imm(False, 0x1f)));
   2742             /* or   v0, a3, v0 */
   2743             addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
   2744 
   2745             /* movn    v0, v1, a0 */
   2746             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
   2747             /* movn    v1, a1, a0 */
   2748             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a1tmp, a0tmp));
   2749 
   2750             *rHi = v1;
   2751             *rLo = v0;
   2752             return;
   2753          }
   2754 
   2755          case Iop_F32toI64S: {
   2756             HReg tmpD = newVRegD(env);
   2757             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
   2758             HReg tLo  = newVRegI(env);
   2759             HReg tHi  = newVRegI(env);
   2760             MIPSAMode *am_addr;
   2761 
   2762             /* CVTLS tmpD, valF */
   2763             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   2764             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
   2765             set_MIPS_rounding_default(env);
   2766 
   2767             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
   2768             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2769 
   2770             /* store as F64 */
   2771             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
   2772                                            am_addr));
   2773             /* load as 2xI32 */
   2774 #if defined (_MIPSEL)
   2775             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
   2776             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
   2777                                          mode64));
   2778 #elif defined (_MIPSEB)
   2779             addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
   2780             addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
   2781                                          mode64));
   2782 #endif
   2783 
   2784             /* Reset SP */
   2785             add_to_sp(env, 16);
   2786 
   2787             *rHi = tHi;
   2788             *rLo = tLo;
   2789 
   2790             return;
   2791          }
   2792 
   2793          default:
   2794             break;
   2795       }
   2796    }
   2797 
   2798    /* --------- UNARY ops --------- */
   2799    if (e->tag == Iex_Unop) {
   2800       switch (e->Iex.Unop.op) {
   2801          case Iop_1Sto64: {
   2802             HReg tLo = newVRegI(env);
   2803             HReg tHi = newVRegI(env);
   2804             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2805             HReg tmp = newVRegI(env);
   2806 
   2807             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
   2808                           MIPSRH_Imm(False, 31)));
   2809             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
   2810                           MIPSRH_Imm(False, 31)));
   2811 
   2812             addInstr(env, mk_iMOVds_RR(tHi, tmp));
   2813             addInstr(env, mk_iMOVds_RR(tLo, tmp));
   2814 
   2815             *rHi = tHi;
   2816             *rLo = tLo;
   2817             return;
   2818          }
   2819 
   2820          /* 32Sto64(e) */
   2821          case Iop_32Sto64: {
   2822             HReg tLo = newVRegI(env);
   2823             HReg tHi = newVRegI(env);
   2824             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2825             addInstr(env, mk_iMOVds_RR(tHi, src));
   2826             addInstr(env, mk_iMOVds_RR(tLo, src));
   2827             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
   2828                           MIPSRH_Imm(False, 31)));
   2829             *rHi = tHi;
   2830             *rLo = tLo;
   2831             return;
   2832          }
   2833 
   2834          /* 8Uto64(e) */
   2835          case Iop_8Uto64: {
   2836             HReg tLo = newVRegI(env);
   2837             HReg tHi = newVRegI(env);
   2838             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2839             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo, src,
   2840                                         MIPSRH_Imm(False, 0xFF)));
   2841             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
   2842                                         MIPSRH_Reg(hregMIPS_GPR0(mode64))));
   2843             *rHi = tHi;
   2844             *rLo = tLo;
   2845             return;
   2846          }
   2847 
   2848          /* 32Uto64(e) */
   2849          case Iop_32Uto64: {
   2850             HReg tLo = newVRegI(env);
   2851             HReg tHi = newVRegI(env);
   2852             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
   2853             addInstr(env, mk_iMOVds_RR(tLo, src));
   2854             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
   2855                           MIPSRH_Reg(hregMIPS_GPR0(mode64))));
   2856             *rHi = tHi;
   2857             *rLo = tLo;
   2858             return;
   2859          }
   2860 
   2861          case Iop_Left64: {
   2862             HReg yHi, yLo;
   2863             HReg tHi  = newVRegI(env);
   2864             HReg tLo  = newVRegI(env);
   2865             HReg tmp  = newVRegI(env);
   2866             HReg tmp1  = newVRegI(env);
   2867             HReg tmp2  = newVRegI(env);
   2868             HReg zero = newVRegI(env);
   2869             MIPSCondCode cc = MIPScc_LO;
   2870 
   2871             /* yHi:yLo = arg */
   2872             iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
   2873             /* zero = 0 */
   2874             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
   2875 
   2876             /* tmp2:tmp1 = 0 - (yHi:yLo)*/
   2877             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, zero, MIPSRH_Reg(yLo)));
   2878             addInstr(env, MIPSInstr_Cmp(False, True, tmp1, zero, tmp2, cc));
   2879             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, zero, MIPSRH_Reg(yHi)));
   2880             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp1, tmp, MIPSRH_Reg(tmp1)));
   2881 
   2882             /* So now we have tmp2:tmp1 = -arg.  To finish off, or 'arg'
   2883                back in, so as to give the final result
   2884                tHi:tLo = arg | -arg. */
   2885             addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, yHi, MIPSRH_Reg(tmp1)));
   2886             addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, yLo, MIPSRH_Reg(tmp2)));
   2887             *rHi = tHi;
   2888             *rLo = tLo;
   2889             return;
   2890          }
   2891 
   2892          case Iop_CmpwNEZ64: {
   2893             HReg srcLo, srcHi;
   2894             HReg tmp1 = newVRegI(env);
   2895             HReg tmp2 = newVRegI(env);
   2896             /* srcHi:srcLo = arg */
   2897             iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
   2898             /* tmp1 = srcHi | srcLo */
   2899             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
   2900                                         MIPSRH_Reg(srcHi)));
   2901             /* tmp2 = (tmp1 | -tmp1) >>s 31 */
   2902 
   2903             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
   2904                                         MIPSRH_Reg(tmp1)));
   2905 
   2906             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
   2907             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
   2908                           MIPSRH_Imm(False, 31)));
   2909             *rHi = tmp2;
   2910             *rLo = tmp2;
   2911             return;
   2912 
   2913          }
   2914          case Iop_ReinterpF64asI64: {
   2915             HReg tLo = newVRegI(env);
   2916             HReg tHi = newVRegI(env);
   2917             MIPSAMode *am_addr;
   2918             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
   2919 
   2920             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
   2921             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   2922 
   2923             /* store as F64 */
   2924             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   2925                                            am_addr));
   2926             /* load as 2xI32 */
   2927 #if defined (_MIPSEL)
   2928             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
   2929             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
   2930                                          mode64));
   2931 #elif defined (_MIPSEB)
   2932             addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
   2933             addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
   2934                                          mode64));
   2935 #endif
   2936 
   2937             /* Reset SP */
   2938             add_to_sp(env, 16);
   2939 
   2940             *rHi = tHi;
   2941             *rLo = tLo;
   2942             return;
   2943          }
   2944 
   2945          default:
   2946             vex_printf("UNARY: No such op: ");
   2947             ppIROp(e->Iex.Unop.op);
   2948             vex_printf("\n");
   2949             break;
   2950       }
   2951    }
   2952 
   2953    vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
   2954    ppIRExpr(e);
   2955    vpanic("iselInt64Expr(mips)");
   2956 }
   2957 
   2958 /*---------------------------------------------------------*/
   2959 /*--- ISEL: Floating point expressions (32 bit)         ---*/
   2960 /*---------------------------------------------------------*/
   2961 
   2962 /* Nothing interesting here; really just wrappers for
   2963    64-bit stuff. */
   2964 static HReg iselFltExpr(ISelEnv * env, IRExpr * e)
   2965 {
   2966    HReg r = iselFltExpr_wrk(env, e);
   2967    vassert(hregIsVirtual(r));
   2968    return r;
   2969 }
   2970 
   2971 /* DO NOT CALL THIS DIRECTLY */
   2972 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
   2973 {
   2974    IRType ty = typeOfIRExpr(env->type_env, e);
   2975    vassert(ty == Ity_F32 || (ty == Ity_F64 && fp_mode64));
   2976 
   2977    if (e->tag == Iex_RdTmp) {
   2978       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   2979    }
   2980 
   2981    if (e->tag == Iex_Load) {
   2982       vassert(e->Iex.Load.ty == Ity_F32
   2983               || (e->Iex.Load.ty == Ity_F64 && fp_mode64));
   2984       HReg r_dst;
   2985       MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
   2986       if (e->Iex.Load.ty == Ity_F64) {
   2987          r_dst = newVRegD(env);
   2988          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
   2989       } else {
   2990          r_dst = newVRegF(env);
   2991          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
   2992       }
   2993       return r_dst;
   2994    }
   2995 
   2996    if (e->tag == Iex_Get) {
   2997       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   2998                                         GuestStatePointer(mode64));
   2999       HReg r_dst;
   3000       if (e->Iex.Load.ty == Ity_F64) {
   3001          r_dst = newVRegD(env);
   3002          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
   3003       } else {
   3004          r_dst = newVRegF(env);
   3005          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
   3006       }
   3007       return r_dst;
   3008    }
   3009 
   3010    if (e->tag == Iex_Unop) {
   3011       switch (e->Iex.Unop.op) {
   3012       case Iop_ReinterpI32asF32: {
   3013          HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   3014          HReg r_dst = newVRegF(env);
   3015 
   3016          /* Move Word to Floating Point
   3017             mtc1 r_dst, valS */
   3018          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, fr_src));
   3019 
   3020          return r_dst;
   3021       }
   3022       case Iop_F32toF64: {
   3023          vassert(fp_mode64);
   3024          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3025          HReg dst = newVRegD(env);
   3026 
   3027          addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
   3028          return dst;
   3029       }
   3030       case Iop_ReinterpI64asF64: {
   3031          HReg r_dst;
   3032          if (mode64) {
   3033             HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   3034             r_dst = newVRegF(env);
   3035             /* Move Doubleword to Floating Point
   3036                dmtc1 r_dst, fr_src */
   3037             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
   3038          } else {
   3039              HReg Hi, Lo;
   3040              r_dst = newVRegD(env);
   3041              iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
   3042              r_dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
   3043          }
   3044          return r_dst;
   3045       }
   3046       case Iop_I32StoF64: {
   3047          vassert(fp_mode64);
   3048          HReg dst = newVRegF(env);
   3049          HReg tmp = newVRegF(env);
   3050          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   3051 
   3052          /* Move Word to Floating Point
   3053             mtc1 tmp, r_src */
   3054          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
   3055 
   3056          /* and do convert */
   3057          addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
   3058 
   3059          return dst;
   3060       }
   3061       case Iop_AbsF32:
   3062       case Iop_AbsF64: {
   3063          Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
   3064          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3065          HReg dst = newVRegF(env);
   3066          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
   3067          return dst;
   3068       }
   3069       case Iop_NegF32:
   3070       case Iop_NegF64: {
   3071          Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
   3072          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3073          HReg dst = newVRegF(env);
   3074          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
   3075          return dst;
   3076       }
   3077       case Iop_RoundF64toF64_ZERO: {
   3078          vassert(mode64);
   3079          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3080          HReg dst = newVRegF(env);
   3081          addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, dst, src));
   3082          return dst;
   3083       }
   3084       case Iop_RoundF64toF64_NEAREST: {
   3085          vassert(mode64);
   3086          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3087          HReg dst = newVRegF(env);
   3088          addInstr(env, MIPSInstr_FpConvert(Mfp_ROUNDLD, dst, src));
   3089          return dst;
   3090       }
   3091       case Iop_RoundF64toF64_NegINF: {
   3092          vassert(mode64);
   3093          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3094          HReg dst = newVRegF(env);
   3095          addInstr(env, MIPSInstr_FpConvert(Mfp_FLOORLD, dst, src));
   3096          return dst;
   3097       }
   3098       case Iop_RoundF64toF64_PosINF: {
   3099          vassert(mode64);
   3100          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3101          HReg dst = newVRegF(env);
   3102          addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, dst, src));
   3103          return dst;
   3104       }
   3105 
   3106       default:
   3107          break;
   3108       }
   3109    }
   3110 
   3111    if (e->tag == Iex_Triop) {
   3112       switch (e->Iex.Triop.details->op) {
   3113          case Iop_DivF32:
   3114          case Iop_DivF64:
   3115          case Iop_MulF32:
   3116          case Iop_MulF64:
   3117          case Iop_AddF32:
   3118          case Iop_AddF64:
   3119          case Iop_SubF32:
   3120          case Iop_SubF64: {
   3121             MIPSFpOp op = 0;
   3122             HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
   3123             HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
   3124             HReg dst = newVRegF(env);
   3125             switch (e->Iex.Triop.details->op) {
   3126                case Iop_DivF32:
   3127                   op = Mfp_DIVS;
   3128                   break;
   3129                case Iop_DivF64:
   3130                   vassert(fp_mode64);
   3131                   op = Mfp_DIVD;
   3132                   break;
   3133                case Iop_MulF32:
   3134                   op = Mfp_MULS;
   3135                   break;
   3136                case Iop_MulF64:
   3137                   vassert(fp_mode64);
   3138                   op = Mfp_MULD;
   3139                   break;
   3140                case Iop_AddF32:
   3141                   op = Mfp_ADDS;
   3142                   break;
   3143                case Iop_AddF64:
   3144                   vassert(fp_mode64);
   3145                   op = Mfp_ADDD;
   3146                   break;
   3147                case Iop_SubF32:
   3148                   op = Mfp_SUBS;
   3149                   break;
   3150                case Iop_SubF64:
   3151                   vassert(fp_mode64);
   3152                   op = Mfp_SUBD;
   3153                   break;
   3154                default:
   3155                   vassert(0);
   3156             }
   3157             set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
   3158             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
   3159             set_MIPS_rounding_default(env);
   3160             return dst;
   3161          }
   3162          default:
   3163             break;
   3164       }
   3165    }
   3166 
   3167    if (e->tag == Iex_Binop) {
   3168       switch (e->Iex.Binop.op) {
   3169          case Iop_F64toF32: {
   3170             HReg valD;
   3171             if (mode64)
   3172                valD = iselFltExpr(env, e->Iex.Binop.arg2);
   3173             else
   3174                valD = iselDblExpr(env, e->Iex.Binop.arg2);
   3175             HReg valS = newVRegF(env);
   3176 
   3177             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3178             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
   3179             set_MIPS_rounding_default(env);
   3180             return valS;
   3181          }
   3182 
   3183          case Iop_RoundF32toInt: {
   3184                HReg valS = newVRegF(env);
   3185                HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
   3186 
   3187                set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3188                addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
   3189                set_MIPS_rounding_default(env);
   3190                return valS;
   3191             }
   3192 
   3193          case Iop_RoundF64toInt: {
   3194             HReg valS = newVRegF(env);
   3195             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
   3196 
   3197             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3198             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, valS, valF));
   3199             set_MIPS_rounding_default(env);
   3200             return valS;
   3201          }
   3202 
   3203          case Iop_I32StoF32: {
   3204             HReg r_dst = newVRegF(env);
   3205             HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
   3206             HReg tmp = newVRegF(env);
   3207 
   3208             /* Move Word to Floating Point
   3209                mtc1 tmp, fr_src */
   3210             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, fr_src));
   3211 
   3212             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3213             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
   3214             set_MIPS_rounding_default(env);
   3215 
   3216             return r_dst;
   3217          }
   3218 
   3219          case Iop_I64StoF64: {
   3220             HReg r_dst = newVRegF(env);
   3221             MIPSAMode *am_addr;
   3222             HReg tmp, fr_src;
   3223             if (mode64) {
   3224                tmp = newVRegF(env);
   3225                fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
   3226                /* Move SP down 8 bytes */
   3227                sub_from_sp(env, 8);
   3228                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   3229 
   3230                /* store as I64 */
   3231                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
   3232 
   3233                /* load as Ity_F64 */
   3234                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
   3235 
   3236                /* Reset SP */
   3237                add_to_sp(env, 8);
   3238             } else {
   3239                HReg Hi, Lo;
   3240                tmp = newVRegD(env);
   3241                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
   3242                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
   3243             }
   3244 
   3245             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3246             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
   3247             set_MIPS_rounding_default(env);
   3248 
   3249             return r_dst;
   3250          }
   3251 
   3252          case Iop_I64StoF32: {
   3253             HReg r_dst = newVRegF(env);
   3254             MIPSAMode *am_addr;
   3255             HReg fr_src, tmp;
   3256             if (mode64) {
   3257                tmp = newVRegF(env);
   3258                fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
   3259                /* Move SP down 8 bytes */
   3260                sub_from_sp(env, 8);
   3261                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
   3262 
   3263                /* store as I64 */
   3264                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
   3265 
   3266                /* load as Ity_F64 */
   3267                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
   3268 
   3269                /* Reset SP */
   3270                add_to_sp(env, 8);
   3271             } else {
   3272                HReg Hi, Lo;
   3273                tmp = newVRegD(env);
   3274                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
   3275                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
   3276             }
   3277 
   3278             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3279             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSL, r_dst, tmp));
   3280             set_MIPS_rounding_default(env);
   3281 
   3282             return r_dst;
   3283          }
   3284 
   3285          case Iop_SqrtF32:
   3286          case Iop_SqrtF64: {
   3287             Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
   3288             HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
   3289             HReg dst = newVRegF(env);
   3290             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3291             addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
   3292                                             src));
   3293             set_MIPS_rounding_default(env);
   3294             return dst;
   3295          }
   3296 
   3297          default:
   3298             break;
   3299       }
   3300    }
   3301 
   3302    if (e->tag == Iex_Qop) {
   3303       switch (e->Iex.Qop.details->op) {
   3304          case Iop_MAddF32:
   3305          case Iop_MAddF64:
   3306          case Iop_MSubF32:
   3307          case Iop_MSubF64: {
   3308             MIPSFpOp op = 0;
   3309             switch (e->Iex.Qop.details->op) {
   3310                case Iop_MAddF32:
   3311                   op = Mfp_MADDS;
   3312                   break;
   3313                case Iop_MAddF64:
   3314                   op = Mfp_MADDD;
   3315                   break;
   3316                case Iop_MSubF32:
   3317                   op = Mfp_MSUBS;
   3318                   break;
   3319                case Iop_MSubF64:
   3320                   op = Mfp_MSUBD;
   3321                   break;
   3322                default:
   3323                   vassert(0);
   3324             }
   3325             HReg dst = newVRegF(env);
   3326             HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
   3327             HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
   3328             HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
   3329             set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
   3330             addInstr(env, MIPSInstr_FpTernary(op, dst,
   3331                                               src1, src2, src3));
   3332             set_MIPS_rounding_default(env);
   3333             return dst;
   3334          }
   3335 
   3336          default:
   3337          break;
   3338       }
   3339    }
   3340 
   3341    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
   3342       /* This is quite subtle.  The only way to do the relevant
   3343          truncation is to do a single-precision store and then a
   3344          double precision load to get it back into a register.  The
   3345          problem is, if the data is then written to memory a second
   3346          time, as in
   3347 
   3348          STbe(...) = TruncF64asF32(...)
   3349 
   3350          then will the second truncation further alter the value?  The
   3351          answer is no: flds (as generated here) followed by fsts
   3352          (generated for the STbe) is the identity function on 32-bit
   3353          floats, so we are safe.
   3354 
   3355          Another upshot of this is that if iselStmt can see the
   3356          entirety of
   3357 
   3358          STbe(...) = TruncF64asF32(arg)
   3359 
   3360          then it can short circuit having to deal with TruncF64asF32
   3361          individually; instead just compute arg into a 64-bit FP
   3362          register and do 'fsts' (since that itself does the
   3363          truncation).
   3364 
   3365          We generate pretty poor code here (should be ok both for
   3366          32-bit and 64-bit mode); but it is expected that for the most
   3367          part the latter optimisation will apply and hence this code
   3368          will not often be used.
   3369        */
   3370       HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
   3371       HReg fdst = newVRegF(env);
   3372       MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
   3373 
   3374       sub_from_sp(env, 16);
   3375       /* store as F32, hence truncating */
   3376       addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
   3377       /* and reload.  Good huh?! (sigh) */
   3378       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
   3379       add_to_sp(env, 16);
   3380       return fdst;
   3381    }
   3382 
   3383    /* --------- ITE --------- */
   3384    if (e->tag == Iex_ITE) {
   3385       if (ty == Ity_F64
   3386           && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
   3387          vassert(mode64);
   3388          HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
   3389          HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
   3390          HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
   3391          HReg r_dst = newVRegF(env);
   3392          addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
   3393          addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
   3394                                             r_cond));
   3395          return r_dst;
   3396       }
   3397    }
   3398 
   3399    vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
   3400    ppIRExpr(e);
   3401    vpanic("iselFltExpr_wrk(mips)");
   3402 }
   3403 
   3404 static HReg iselDblExpr(ISelEnv * env, IRExpr * e)
   3405 {
   3406    HReg r = iselDblExpr_wrk(env, e);
   3407    vassert(hregClass(r) == HRcFlt64);
   3408    vassert(hregIsVirtual(r));
   3409    return r;
   3410 }
   3411 
   3412 /* DO NOT CALL THIS DIRECTLY */
   3413 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
   3414 {
   3415    IRType ty = typeOfIRExpr(env->type_env, e);
   3416    vassert(e);
   3417    vassert(ty == Ity_F64);
   3418 
   3419    if (e->tag == Iex_RdTmp) {
   3420       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   3421    }
   3422 
   3423    /* --------- LOAD --------- */
   3424    if (e->tag == Iex_Load) {
   3425       HReg r_dst = newVRegD(env);
   3426       MIPSAMode *am_addr;
   3427       vassert(e->Iex.Load.ty == Ity_F64);
   3428       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
   3429       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   3430       return r_dst;
   3431    }
   3432 
   3433    /* --------- GET --------- */
   3434    if (e->tag == Iex_Get) {
   3435 
   3436       HReg r_dst = newVRegD(env);
   3437       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
   3438                                         GuestStatePointer(mode64));
   3439       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
   3440       return r_dst;
   3441    }
   3442 
   3443    if (e->tag == Iex_Unop) {
   3444       MIPSFpOp fpop = Mfp_INVALID;
   3445       switch (e->Iex.Unop.op) {
   3446          case Iop_NegF64:
   3447             fpop = Mfp_NEGD;
   3448             break;
   3449          case Iop_AbsF64:
   3450             fpop = Mfp_ABSD;
   3451             break;
   3452          case Iop_F32toF64: {
   3453             vassert(!mode64);
   3454             HReg src = iselFltExpr(env, e->Iex.Unop.arg);
   3455             HReg dst = newVRegD(env);
   3456 
   3457             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
   3458             return dst;
   3459          }
   3460          case Iop_ReinterpI64asF64: {
   3461             HReg Hi, Lo;
   3462             HReg dst = newVRegD(env);
   3463 
   3464             iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
   3465 
   3466             dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
   3467             return dst;
   3468          }
   3469          case Iop_I32StoF64: {
   3470             vassert(!mode64);
   3471             HReg dst = newVRegD(env);
   3472             HReg tmp = newVRegF(env);
   3473             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
   3474 
   3475             /* Move Word to Floating Point
   3476                mtc1 tmp, r_src */
   3477             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
   3478 
   3479             /* and do convert */
   3480             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
   3481 
   3482             return dst;
   3483          }
   3484          default:
   3485             break;
   3486       }
   3487 
   3488       if (fpop != Mfp_INVALID) {
   3489          HReg src = iselDblExpr(env, e->Iex.Unop.arg);
   3490          HReg dst = newVRegD(env);
   3491          addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
   3492          return dst;
   3493       }
   3494    }
   3495 
   3496    if (e->tag == Iex_Binop) {
   3497       switch (e->Iex.Binop.op) {
   3498          case Iop_RoundF64toInt: {
   3499             HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
   3500             HReg dst = newVRegD(env);
   3501 
   3502             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3503             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, dst, src));
   3504             set_MIPS_rounding_default(env);
   3505 
   3506             return dst;
   3507          }
   3508 
   3509          case Iop_SqrtF64: {
   3510             HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
   3511             HReg dst = newVRegD(env);
   3512             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
   3513             addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
   3514             set_MIPS_rounding_default(env);
   3515             return dst;
   3516          }
   3517 
   3518          default:
   3519             break;
   3520 
   3521       }
   3522    }
   3523 
   3524    if (e->tag == Iex_Triop) {
   3525       switch (e->Iex.Triop.details->op) {
   3526          case Iop_DivF64:
   3527          case Iop_DivF32:
   3528          case Iop_MulF64:
   3529          case Iop_AddF64:
   3530          case Iop_SubF64: {
   3531             MIPSFpOp op = 0;
   3532             HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
   3533             HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
   3534             HReg dst = newVRegD(env);
   3535             switch (e->Iex.Triop.details->op) {
   3536                case Iop_DivF64:
   3537                   op = Mfp_DIVD;
   3538                   break;
   3539                case Iop_DivF32:
   3540                   op = Mfp_DIVS;
   3541                   break;
   3542                case Iop_MulF64:
   3543                   op = Mfp_MULD;
   3544                   break;
   3545                case Iop_AddF64:
   3546                   op = Mfp_ADDD;
   3547                   break;
   3548                case Iop_SubF64:
   3549                   op = Mfp_SUBD;
   3550                   break;
   3551                default:
   3552                   vassert(0);
   3553             }
   3554             set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
   3555             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
   3556             set_MIPS_rounding_default(env);
   3557             return dst;
   3558          }
   3559          default:
   3560             break;
   3561       }
   3562    }
   3563 
   3564    if (e->tag == Iex_Qop) {
   3565       switch (e->Iex.Qop.details->op) {
   3566          case Iop_MAddF32:
   3567          case Iop_MAddF64:
   3568          case Iop_MSubF32:
   3569          case Iop_MSubF64: {
   3570             MIPSFpOp op = 0;
   3571             switch (e->Iex.Qop.details->op) {
   3572                case Iop_MAddF32:
   3573                   op = Mfp_MADDS;
   3574                   break;
   3575                case Iop_MAddF64:
   3576                   op = Mfp_MADDD;
   3577                   break;
   3578                case Iop_MSubF32:
   3579                   op = Mfp_MSUBS;
   3580                   break;
   3581                case Iop_MSubF64:
   3582                   op = Mfp_MSUBD;
   3583                   break;
   3584                default:
   3585                   vassert(0);
   3586             }
   3587             HReg dst = newVRegD(env);
   3588             HReg src1 = iselDblExpr(env, e->Iex.Qop.details->arg2);
   3589             HReg src2 = iselDblExpr(env, e->Iex.Qop.details->arg3);
   3590             HReg src3 = iselDblExpr(env, e->Iex.Qop.details->arg4);
   3591             set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
   3592             addInstr(env, MIPSInstr_FpTernary(op, dst,
   3593                                               src1, src2, src3));
   3594             set_MIPS_rounding_default(env);
   3595             return dst;
   3596          }
   3597 
   3598          default:
   3599          break;
   3600       }
   3601    }
   3602 
   3603    /* --------- ITE --------- */
   3604    if (e->tag == Iex_ITE) {
   3605       if (ty == Ity_F64
   3606           && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
   3607          HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse);
   3608          HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue);
   3609          HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
   3610          HReg r_dst = newVRegD(env);
   3611 
   3612          addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
   3613          addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
   3614                                             r_cond));
   3615          return r_dst;
   3616       }
   3617    }
   3618 
   3619    vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
   3620    ppIRExpr(e);
   3621    vpanic("iselDblExpr_wrk(mips)");
   3622 }
   3623 
   3624 /*---------------------------------------------------------*/
   3625 /*--- ISEL: Statements                                  ---*/
   3626 /*---------------------------------------------------------*/
   3627 
   3628 static void iselStmt(ISelEnv * env, IRStmt * stmt)
   3629 {
   3630    if (vex_traceflags & VEX_TRACE_VCODE) {
   3631       vex_printf("\n-- ");
   3632 
   3633       ppIRStmt(stmt);
   3634       vex_printf("\n");
   3635    }
   3636 
   3637    switch (stmt->tag) {
   3638       /* --------- STORE --------- */
   3639       case Ist_Store: {
   3640          MIPSAMode *am_addr;
   3641          IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   3642 
   3643          /*constructs addressing mode from address provided */
   3644          am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
   3645 
   3646          if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
   3647              (mode64 && (tyd == Ity_I64))) {
   3648             HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
   3649             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
   3650                      am_addr, r_src, mode64));
   3651             return;
   3652          }
   3653          if (!mode64 && (tyd == Ity_I64)) {
   3654             HReg vHi, vLo;
   3655             HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
   3656 
   3657             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
   3658 
   3659             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   3660                           MIPSAMode_IR(0, r_addr), vHi, mode64));
   3661             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   3662                           MIPSAMode_IR(4, r_addr), vLo, mode64));
   3663             return;
   3664          }
   3665          if (tyd == Ity_F32) {
   3666             HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
   3667             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
   3668                                            am_addr));
   3669             return;
   3670          }
   3671          if (tyd == Ity_F64 && mode64) {
   3672             HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
   3673             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   3674                                            am_addr));
   3675             return;
   3676          }
   3677          if (!mode64 && (tyd == Ity_F64)) {
   3678             HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
   3679             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   3680                                            am_addr));
   3681             return;
   3682          }
   3683 
   3684          break;
   3685       }
   3686 
   3687       /* --------- PUT --------- */
   3688       case Ist_Put: {
   3689          IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   3690 
   3691          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   3692              (ty == Ity_I64 && mode64)) {
   3693             HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
   3694             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   3695                                               GuestStatePointer(mode64));
   3696             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
   3697                                           am_addr, r_src, mode64));
   3698             return;
   3699          }
   3700 
   3701          if (ty == Ity_I64 && !mode64) {
   3702             HReg vHi, vLo;
   3703             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   3704                                               GuestStatePointer(mode64));
   3705             MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
   3706                                                GuestStatePointer(mode64));
   3707             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
   3708             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   3709                                           am_addr, vLo, mode64));
   3710             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
   3711                                           am_addr4, vHi, mode64));
   3712             return;
   3713 
   3714          }
   3715 
   3716          if (ty == Ity_F32) {
   3717             HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
   3718             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   3719                                               GuestStatePointer(mode64));
   3720             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
   3721                                            am_addr));
   3722             return;
   3723          }
   3724 
   3725          if (ty == Ity_F64) {
   3726             HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
   3727             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
   3728                                               GuestStatePointer(mode64));
   3729             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
   3730                                            am_addr));
   3731             return;
   3732          }
   3733          break;
   3734       }
   3735 
   3736       /* --------- TMP --------- */
   3737       case Ist_WrTmp: {
   3738          IRTemp tmp = stmt->Ist.WrTmp.tmp;
   3739          IRType ty = typeOfIRTemp(env->type_env, tmp);
   3740 
   3741          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
   3742             HReg r_dst = lookupIRTemp(env, tmp);
   3743             HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
   3744             addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   3745             return;
   3746          }
   3747 
   3748          if (ty == Ity_I64) {
   3749             if (mode64) {
   3750                HReg r_dst = lookupIRTemp(env, tmp);
   3751                HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
   3752                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   3753                return;
   3754             } else {
   3755                HReg rHi, rLo, dstHi, dstLo;
   3756                iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
   3757                lookupIRTemp64(&dstHi, &dstLo, env, tmp);
   3758                addInstr(env, mk_iMOVds_RR(dstHi, rHi));
   3759                addInstr(env, mk_iMOVds_RR(dstLo, rLo));
   3760                return;
   3761             }
   3762          }
   3763 
   3764          if (mode64 && ty == Ity_I128) {
   3765             HReg rHi, rLo, dstHi, dstLo;
   3766             iselInt128Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
   3767             lookupIRTempPair(&dstHi, &dstLo, env, tmp);
   3768             addInstr(env, mk_iMOVds_RR(dstHi, rHi));
   3769             addInstr(env, mk_iMOVds_RR(dstLo, rLo));
   3770             return;
   3771          }
   3772 
   3773          if (ty == Ity_F32) {
   3774             HReg fr_dst = lookupIRTemp(env, tmp);
   3775             HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
   3776             addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
   3777             return;
   3778          }
   3779 
   3780          if (ty == Ity_F64) {
   3781             if (mode64) {
   3782                HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
   3783                HReg dst = lookupIRTemp(env, tmp);
   3784                addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
   3785                return;
   3786             } else {
   3787                HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
   3788                HReg dst = lookupIRTemp(env, tmp);
   3789                addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
   3790                return;
   3791             }
   3792          }
   3793          break;
   3794       }
   3795 
   3796       /* --------- Call to DIRTY helper --------- */
   3797       case Ist_Dirty: {
   3798          IRDirty *d = stmt->Ist.Dirty.details;
   3799 
   3800          /* Figure out the return type, if any. */
   3801          IRType retty = Ity_INVALID;
   3802          if (d->tmp != IRTemp_INVALID)
   3803             retty = typeOfIRTemp(env->type_env, d->tmp);
   3804 
   3805          /* Throw out any return types we don't know about. */
   3806          Bool retty_ok = False;
   3807          switch (retty) {
   3808             case Ity_INVALID: /* Function doesn't return anything. */
   3809             case Ity_V128:
   3810             case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
   3811                retty_ok = True; break;
   3812             default:
   3813                break;
   3814          }
   3815 
   3816          if (!retty_ok)
   3817             break; /* will go to stmt_fail: */
   3818 
   3819          /* Marshal args, do the call, clear stack, set the return value
   3820             to 0x555..555 if this is a conditional call that returns a
   3821             value and the call is skipped. */
   3822          UInt   addToSp = 0;
   3823          RetLoc rloc    = mk_RetLoc_INVALID();
   3824          doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args );
   3825          vassert(is_sane_RetLoc(rloc));
   3826 
   3827          /* Now figure out what to do with the returned value, if any. */
   3828          switch (retty) {
   3829             case Ity_INVALID: {
   3830                /* No return value.  Nothing to do. */
   3831                vassert(d->tmp == IRTemp_INVALID);
   3832                vassert(rloc.pri == RLPri_None);
   3833                vassert(addToSp == 0);
   3834                return;
   3835             }
   3836             case Ity_I32: case Ity_I16: case Ity_I8: {
   3837                /* The returned value is in $v0.  Park it in the register
   3838                   associated with tmp. */
   3839                HReg r_dst = lookupIRTemp(env, d->tmp);
   3840                addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
   3841                vassert(rloc.pri == RLPri_Int);
   3842                vassert(addToSp == 0);
   3843                return;
   3844             }
   3845             case Ity_I64: {
   3846                if (mode64) {
   3847                   /* The returned value is in $v0.  Park it in the register
   3848                      associated with tmp. */
   3849                   HReg r_dst = lookupIRTemp(env, d->tmp);
   3850                   addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
   3851                   vassert(rloc.pri == RLPri_Int);
   3852                   vassert(addToSp == 0);
   3853                   return;
   3854                } else {
   3855                   HReg rHi = newVRegI(env);
   3856                   HReg rLo = newVRegI(env);
   3857                   HReg dstHi, dstLo;
   3858                   addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64)));
   3859                   addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64)));
   3860                   lookupIRTemp64(&dstHi, &dstLo, env, d->tmp);
   3861                   addInstr(env, mk_iMOVds_RR(dstHi, rHi));
   3862                   addInstr(env, mk_iMOVds_RR(dstLo, rLo));
   3863                   return;
   3864                }
   3865             }
   3866             case Ity_V128: {
   3867                /* ATC. The code that this produces really
   3868                   needs to be looked at, to verify correctness.
   3869                   I don't think this can ever happen though, since the
   3870                   MIPS front end never produces 128-bit loads/stores. */
   3871                vassert(0);
   3872                vassert(rloc.pri == RLPri_V128SpRel);
   3873                vassert(addToSp >= 16);
   3874                HReg       dst = lookupIRTemp(env, d->tmp);
   3875                MIPSAMode* am  = MIPSAMode_IR(rloc.spOff, StackPointer(mode64));
   3876                addInstr(env, MIPSInstr_Load(mode64 ? 8 : 4, dst, am, mode64));
   3877                add_to_sp(env, addToSp);
   3878                return;
   3879 
   3880             }
   3881             default:
   3882                /*NOTREACHED*/
   3883                vassert(0);
   3884          }
   3885       }
   3886 
   3887       /* --------- Load Linked or Store Conditional --------- */
   3888       case Ist_LLSC: {
   3889          /* Temporary solution; this need to be rewritten again for MIPS.
   3890             On MIPS you can not read from address that is locked with LL
   3891             before SC. If you read from address that is locked than SC will
   3892             fall. */
   3893          IRTemp res = stmt->Ist.LLSC.result;
   3894          IRType tyRes = typeOfIRTemp(env->type_env, res);
   3895          IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
   3896 
   3897          if (!mode64 && (tyAddr != Ity_I32))
   3898             goto stmt_fail;
   3899 
   3900          if (stmt->Ist.LLSC.storedata == NULL) {
   3901             /* LL */
   3902             MIPSAMode *r_addr;
   3903             /* constructs addressing mode from address provided */
   3904             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
   3905 
   3906             HReg r_dst = lookupIRTemp(env, res);
   3907             if (tyRes == Ity_I32) {
   3908                addInstr(env, MIPSInstr_LoadL(4, r_dst, r_addr, mode64));
   3909                return;
   3910             } else if (tyRes == Ity_I64 && mode64) {
   3911                addInstr(env, MIPSInstr_LoadL(8, r_dst, r_addr, mode64));
   3912                return;
   3913             }
   3914          } else {
   3915             /* SC */
   3916             MIPSAMode *r_addr;
   3917             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
   3918             HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
   3919             HReg r_dst = lookupIRTemp(env, res);
   3920             IRType tyData = typeOfIRExpr(env->type_env,
   3921                                          stmt->Ist.LLSC.storedata);
   3922 
   3923             if (tyData == Ity_I32) {
   3924                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   3925                addInstr(env, MIPSInstr_StoreC(4, r_addr, r_dst, mode64));
   3926                return;
   3927             } else if (tyData == Ity_I64 && mode64) {
   3928                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   3929                addInstr(env, MIPSInstr_StoreC(8, r_addr, r_dst, mode64));
   3930                return;
   3931             }
   3932          }
   3933          goto stmt_fail;
   3934        /* NOTREACHED */}
   3935 
   3936    /* --------- INSTR MARK --------- */
   3937    /* Doesn't generate any executable code ... */
   3938    case Ist_IMark:
   3939       return;
   3940 
   3941    /* --------- ABI HINT --------- */
   3942    /* These have no meaning (denotation in the IR) and so we ignore
   3943       them ... if any actually made it this far. */
   3944    case Ist_AbiHint:
   3945       return;
   3946 
   3947    /* --------- NO-OP --------- */
   3948    /* Fairly self-explanatory, wouldn't you say? */
   3949    case Ist_NoOp:
   3950       return;
   3951 
   3952    /* --------- EXIT --------- */
   3953    case Ist_Exit: {
   3954       IRConst* dst = stmt->Ist.Exit.dst;
   3955       if (!mode64 && dst->tag != Ico_U32)
   3956          vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
   3957       if (mode64 && dst->tag != Ico_U64)
   3958          vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
   3959 
   3960       MIPSCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
   3961       MIPSAMode*   amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
   3962                                       GuestStatePointer(mode64));
   3963 
   3964       /* Case: boring transfer to known address */
   3965       if (stmt->Ist.Exit.jk == Ijk_Boring
   3966           || stmt->Ist.Exit.jk == Ijk_Call
   3967           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
   3968          if (env->chainingAllowed) {
   3969             /* .. almost always true .. */
   3970             /* Skip the event check at the dst if this is a forwards
   3971                edge. */
   3972             Bool toFastEP
   3973                = mode64
   3974                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
   3975                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
   3976             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
   3977             addInstr(env, MIPSInstr_XDirect(
   3978                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
   3979                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
   3980                              amPC, cc, toFastEP));
   3981          } else {
   3982             /* .. very occasionally .. */
   3983             /* We can't use chaining, so ask for an assisted transfer,
   3984                as that's the only alternative that is allowable. */
   3985             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   3986             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
   3987          }
   3988          return;
   3989       }
   3990 
   3991       /* Case: assisted transfer to arbitrary address */
   3992       switch (stmt->Ist.Exit.jk) {
   3993          /* Keep this list in sync with that in iselNext below */
   3994          case Ijk_ClientReq:
   3995          case Ijk_EmFail:
   3996          case Ijk_EmWarn:
   3997          case Ijk_NoDecode:
   3998          case Ijk_NoRedir:
   3999          case Ijk_SigBUS:
   4000          case Ijk_SigTRAP:
   4001          case Ijk_SigFPE_IntDiv:
   4002          case Ijk_SigFPE_IntOvf:
   4003          case Ijk_Sys_syscall:
   4004          case Ijk_InvalICache:
   4005          {
   4006             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   4007             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
   4008                                              stmt->Ist.Exit.jk));
   4009             return;
   4010          }
   4011          default:
   4012             break;
   4013       }
   4014 
   4015       /* Do we ever expect to see any other kind? */
   4016       goto stmt_fail;
   4017    }
   4018 
   4019    default:
   4020       break;
   4021    }
   4022 
   4023    stmt_fail:
   4024       vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
   4025       ppIRStmt(stmt);
   4026       vpanic("iselStmt:\n");
   4027 }
   4028 
   4029 /*---------------------------------------------------------*/
   4030 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   4031 /*---------------------------------------------------------*/
   4032 
   4033 static void iselNext ( ISelEnv* env,
   4034                        IRExpr* next, IRJumpKind jk, Int offsIP )
   4035 {
   4036    if (vex_traceflags & VEX_TRACE_VCODE) {
   4037       vex_printf( "\n-- PUT(%d) = ", offsIP);
   4038       ppIRExpr( next );
   4039       vex_printf( "; exit-");
   4040       ppIRJumpKind(jk);
   4041       vex_printf( "\n");
   4042    }
   4043 
   4044    /* Case: boring transfer to known address */
   4045    if (next->tag == Iex_Const) {
   4046       IRConst* cdst = next->Iex.Const.con;
   4047       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
   4048       if (jk == Ijk_Boring || jk == Ijk_Call) {
   4049          /* Boring transfer to known address */
   4050          MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
   4051          if (env->chainingAllowed) {
   4052             /* .. almost always true .. */
   4053             /* Skip the event check at the dst if this is a forwards
   4054                edge. */
   4055             Bool toFastEP
   4056                = env->mode64
   4057                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
   4058                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
   4059             if (0) vex_printf("%s", toFastEP ? "X" : ".");
   4060             addInstr(env, MIPSInstr_XDirect(
   4061                              env->mode64 ? (Addr64)cdst->Ico.U64
   4062                                          : (Addr64)cdst->Ico.U32,
   4063                              amPC, MIPScc_AL, toFastEP));
   4064          } else {
   4065             /* .. very occasionally .. */
   4066             /* We can't use chaining, so ask for an assisted transfer,
   4067                as that's the only alternative that is allowable. */
   4068             HReg r = iselWordExpr_R(env, next);
   4069             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
   4070                                               Ijk_Boring));
   4071          }
   4072          return;
   4073       }
   4074    }
   4075 
   4076    /* Case: call/return (==boring) transfer to any address */
   4077    switch (jk) {
   4078       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
   4079          HReg       r     = iselWordExpr_R(env, next);
   4080          MIPSAMode*  amPC = MIPSAMode_IR(offsIP,
   4081                                          GuestStatePointer(env->mode64));
   4082          if (env->chainingAllowed) {
   4083             addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
   4084          } else {
   4085             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
   4086                                               Ijk_Boring));
   4087          }
   4088          return;
   4089       }
   4090       default:
   4091          break;
   4092    }
   4093 
   4094    /* Case: assisted transfer to arbitrary address */
   4095    switch (jk) {
   4096       /* Keep this list in sync with that for Ist_Exit above */
   4097       case Ijk_ClientReq:
   4098       case Ijk_EmFail:
   4099       case Ijk_EmWarn:
   4100       case Ijk_NoDecode:
   4101       case Ijk_NoRedir:
   4102       case Ijk_SigBUS:
   4103       case Ijk_SigILL:
   4104       case Ijk_SigTRAP:
   4105       case Ijk_SigFPE_IntDiv:
   4106       case Ijk_SigFPE_IntOvf:
   4107       case Ijk_Sys_syscall:
   4108       case Ijk_InvalICache: {
   4109          HReg      r     = iselWordExpr_R(env, next);
   4110          MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
   4111          addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
   4112          return;
   4113       }
   4114       default:
   4115          break;
   4116    }
   4117 
   4118    vex_printf("\n-- PUT(%d) = ", offsIP);
   4119    ppIRExpr(next );
   4120    vex_printf("; exit-");
   4121    ppIRJumpKind(jk);
   4122    vex_printf("\n");
   4123    vassert(0);  /* are we expecting any other kind? */
   4124 }
   4125 
   4126 /*---------------------------------------------------------*/
   4127 /*--- Insn selector top-level                           ---*/
   4128 /*---------------------------------------------------------*/
   4129 
   4130 /* Translate an entire BB to mips code. */
   4131 HInstrArray *iselSB_MIPS ( IRSB* bb,
   4132                            VexArch arch_host,
   4133                            VexArchInfo* archinfo_host,
   4134                            VexAbiInfo* vbi,
   4135                            Int offs_Host_EvC_Counter,
   4136                            Int offs_Host_EvC_FailAddr,
   4137                            Bool chainingAllowed,
   4138                            Bool addProfInc,
   4139                            Addr64 max_ga )
   4140 {
   4141    Int      i, j;
   4142    HReg     hreg, hregHI;
   4143    ISelEnv* env;
   4144    UInt     hwcaps_host = archinfo_host->hwcaps;
   4145    MIPSAMode *amCounter, *amFailAddr;
   4146 
   4147    /* sanity ... */
   4148    vassert(arch_host == VexArchMIPS32 || arch_host == VexArchMIPS64);
   4149    vassert(VEX_PRID_COMP_MIPS == hwcaps_host
   4150            || VEX_PRID_COMP_BROADCOM == hwcaps_host
   4151            || VEX_PRID_COMP_NETLOGIC);
   4152 
   4153    mode64 = arch_host != VexArchMIPS32;
   4154 #if (__mips_fpr==64)
   4155    fp_mode64 = ((VEX_MIPS_REV(hwcaps_host) == VEX_PRID_CPU_32FPR)
   4156                 || arch_host == VexArchMIPS64);
   4157 #endif
   4158 
   4159    /* Make up an initial environment to use. */
   4160    env = LibVEX_Alloc(sizeof(ISelEnv));
   4161    env->vreg_ctr = 0;
   4162    env->mode64 = mode64;
   4163    env->fp_mode64 = fp_mode64;
   4164 
   4165    /* Set up output code array. */
   4166    env->code = newHInstrArray();
   4167 
   4168    /* Copy BB's type env. */
   4169    env->type_env = bb->tyenv;
   4170 
   4171    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   4172       change as we go along. */
   4173    env->n_vregmap = bb->tyenv->types_used;
   4174    env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   4175    env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   4176 
   4177    /* and finally ... */
   4178    env->hwcaps          = hwcaps_host;
   4179    env->chainingAllowed = chainingAllowed;
   4180    env->hwcaps          = hwcaps_host;
   4181    env->max_ga          = max_ga;
   4182 
   4183    /* For each IR temporary, allocate a suitably-kinded virtual
   4184       register. */
   4185    j = 0;
   4186    for (i = 0; i < env->n_vregmap; i++) {
   4187       hregHI = hreg = INVALID_HREG;
   4188       switch (bb->tyenv->types[i]) {
   4189          case Ity_I1:
   4190          case Ity_I8:
   4191          case Ity_I16:
   4192          case Ity_I32:
   4193             if (mode64) {
   4194                hreg = mkHReg(j++, HRcInt64, True);
   4195                break;
   4196             } else {
   4197                hreg = mkHReg(j++, HRcInt32, True);
   4198                break;
   4199             }
   4200          case Ity_I64:
   4201             if (mode64) {
   4202                hreg = mkHReg(j++, HRcInt64, True);
   4203                break;
   4204             } else {
   4205                hreg = mkHReg(j++, HRcInt32, True);
   4206                hregHI = mkHReg(j++, HRcInt32, True);
   4207                break;
   4208             }
   4209          case Ity_I128:
   4210             vassert(mode64);
   4211             hreg = mkHReg(j++, HRcInt64, True);
   4212             hregHI = mkHReg(j++, HRcInt64, True);
   4213             break;
   4214          case Ity_F32:
   4215             if (mode64) {
   4216                hreg = mkHReg(j++, HRcFlt64, True);
   4217                break;
   4218             } else {
   4219                hreg = mkHReg(j++, HRcFlt32, True);
   4220                break;
   4221             }
   4222          case Ity_F64:
   4223             hreg = mkHReg(j++, HRcFlt64, True);
   4224             break;
   4225          default:
   4226             ppIRType(bb->tyenv->types[i]);
   4227             vpanic("iselBB(mips): IRTemp type");
   4228             break;
   4229       }
   4230       env->vregmap[i] = hreg;
   4231       env->vregmapHI[i] = hregHI;
   4232    }
   4233    env->vreg_ctr = j;
   4234 
   4235    /* The very first instruction must be an event check. */
   4236    amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, GuestStatePointer(mode64));
   4237    amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, GuestStatePointer(mode64));
   4238    addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
   4239 
   4240    /* Possibly a block counter increment (for profiling).  At this
   4241       point we don't know the address of the counter, so just pretend
   4242       it is zero.  It will have to be patched later, but before this
   4243       translation is used, by a call to LibVEX_patchProfCtr. */
   4244    if (addProfInc) {
   4245       addInstr(env, MIPSInstr_ProfInc());
   4246    }
   4247 
   4248    /* Ok, finally we can iterate over the statements. */
   4249    for (i = 0; i < bb->stmts_used; i++)
   4250       iselStmt(env, bb->stmts[i]);
   4251 
   4252    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
   4253 
   4254    /* record the number of vregs we used. */
   4255    env->code->n_vregs = env->vreg_ctr;
   4256    return env->code;
   4257 
   4258 }
   4259 
   4260 /*---------------------------------------------------------------*/
   4261 /*--- end                                    host_mips_isel.c ---*/
   4262 /*---------------------------------------------------------------*/
   4263