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