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@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 /* Host hwcaps */
59 static UInt hwcaps_host = 0;
60 
61 /* Host CPU has MSA ASE */
62 static Bool has_msa = False;
63 
64 /* GPR register class for mips32/64 */
65 #define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
66 
67 /* FPR register class for mips32/64 */
68 #define HRcFPR(_mode64) ((_mode64) ? HRcFlt64 : HRcFlt32)
69 
70 /*---------------------------------------------------------*/
71 /*--- ISelEnv                                           ---*/
72 /*---------------------------------------------------------*/
73 
74 /* This carries around:
75 
76    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
77      might encounter.  This is computed before insn selection starts,
78      and does not change.
79 
80    - A mapping from IRTemp to HReg.  This tells the insn selector
81      which virtual register(s) are associated with each IRTemp
82      temporary.  This is computed before insn selection starts, and
83      does not change.  We expect this mapping to map precisely the
84      same set of IRTemps as the type mapping does.
85 
86         - vregmap   holds the primary register for the IRTemp.
87         - vregmapHI is only used for 64-bit integer-typed
88              IRTemps.  It holds the identity of a second
89              32-bit virtual HReg, which holds the high half
90              of the value.
91 
92    - The code array, that is, the insns selected so far.
93 
94    - A counter, for generating new virtual registers.
95 
96    - The host subarchitecture we are selecting insns for.
97      This is set at the start and does not change.
98 
99    - A Bool for indicating whether we may generate chain-me
100      instructions for control flow transfers, or whether we must use
101      XAssisted.
102 
103    - The maximum guest address of any guest insn in this block.
104      Actually, the address of the highest-addressed byte from any insn
105      in this block.  Is set at the start and does not change.  This is
106      used for detecting jumps which are definitely forward-edges from
107      this block, and therefore can be made (chained) to the fast entry
108      point of the destination, thereby avoiding the destination's
109      event check.
110 
111    Note, this is all (well, mostly) host-independent.
112 */
113 
114 typedef
115    struct {
116       /* Constant -- are set at the start and do not change. */
117       IRTypeEnv*   type_env;
118 
119       HReg*        vregmap;
120       HReg*        vregmapHI;
121       Int          n_vregmap;
122 
123       UInt         hwcaps;
124       Bool         mode64;
125       Bool         fp_mode64;
126 
127       Bool         chainingAllowed;
128       Addr64       max_ga;
129 
130       /* These are modified as we go along. */
131       HInstrArray* code;
132       Int          vreg_ctr;
133    }
134    ISelEnv;
135 
lookupIRTemp(ISelEnv * env,IRTemp tmp)136 static HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
137 {
138    vassert(tmp < env->n_vregmap);
139    return env->vregmap[tmp];
140 }
141 
lookupIRTemp64(HReg * vrHI,HReg * vrLO,ISelEnv * env,IRTemp tmp)142 static void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
143 {
144    vassert(tmp < env->n_vregmap);
145    vassert(! hregIsInvalid(env->vregmapHI[tmp]));
146    *vrLO = env->vregmap[tmp];
147    *vrHI = env->vregmapHI[tmp];
148 }
149 
150 static void
lookupIRTempPair(HReg * vrHI,HReg * vrLO,ISelEnv * env,IRTemp tmp)151 lookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
152 {
153    vassert(env->mode64);
154    vassert(tmp < env->n_vregmap);
155    vassert(! hregIsInvalid(env->vregmapHI[tmp]));
156    *vrLO = env->vregmap[tmp];
157    *vrHI = env->vregmapHI[tmp];
158 }
159 
addInstr(ISelEnv * env,MIPSInstr * instr)160 static void addInstr(ISelEnv * env, MIPSInstr * instr)
161 {
162    addHInstr(env->code, instr);
163    if (vex_traceflags & VEX_TRACE_VCODE) {
164       ppMIPSInstr(instr, mode64);
165       vex_printf("\n");
166    }
167 }
168 
newVRegI(ISelEnv * env)169 static HReg newVRegI(ISelEnv * env)
170 {
171    HReg reg = mkHReg(True/*virtual reg*/,
172                      HRcGPR(env->mode64), 0/*enc*/, env->vreg_ctr);
173    env->vreg_ctr++;
174    return reg;
175 }
176 
newVRegD(ISelEnv * env)177 static HReg newVRegD(ISelEnv * env)
178 {
179    HReg reg = mkHReg(True/*virtual reg*/,
180                      HRcFlt64, 0/*enc*/, env->vreg_ctr);
181    env->vreg_ctr++;
182    return reg;
183 }
184 
newVRegF(ISelEnv * env)185 static HReg newVRegF(ISelEnv * env)
186 {
187    HReg reg = mkHReg(True/*virtual reg*/,
188                      HRcFPR(env->mode64), 0/*enc*/, env->vreg_ctr);
189    env->vreg_ctr++;
190    return reg;
191 }
192 
newVRegV(ISelEnv * env)193 static HReg newVRegV ( ISelEnv* env )
194 {
195    HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0, env->vreg_ctr);
196    env->vreg_ctr++;
197    return reg;
198 }
199 
add_to_sp(ISelEnv * env,UInt n)200 static void add_to_sp(ISelEnv * env, UInt n)
201 {
202    HReg sp = StackPointer(mode64);
203    vassert(n < 256 && (n % 8) == 0);
204    if (mode64)
205       addInstr(env, MIPSInstr_Alu(Malu_DADD, sp, sp, MIPSRH_Imm(True,
206                                                                 toUShort(n))));
207    else
208       addInstr(env, MIPSInstr_Alu(Malu_ADD, sp, sp, MIPSRH_Imm(True,
209                                                                toUShort(n))));
210 }
211 
sub_from_sp(ISelEnv * env,UInt n)212 static void sub_from_sp(ISelEnv * env, UInt n)
213 {
214    HReg sp = StackPointer(mode64);
215    vassert(n < 256 && (n % 8) == 0);
216    if (mode64)
217       addInstr(env, MIPSInstr_Alu(Malu_DSUB, sp, sp,
218                                   MIPSRH_Imm(True, toUShort(n))));
219    else
220       addInstr(env, MIPSInstr_Alu(Malu_SUB, sp, sp,
221                                   MIPSRH_Imm(True, toUShort(n))));
222 }
223 
224 /*---------------------------------------------------------*/
225 /*--- ISEL: Forward declarations                        ---*/
226 /*---------------------------------------------------------*/
227 
228 /* These are organised as iselXXX and iselXXX_wrk pairs.  The
229    iselXXX_wrk do the real work, but are not to be called directly.
230    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
231    checks that all returned registers are virtual.  You should not
232    call the _wrk version directly.
233 */
234 /* 32-bit mode: Compute an I8/I16/I32 into a RH
235                 (reg-or-halfword-immediate).
236    It's important to specify whether the immediate is to be regarded
237    as signed or not.  If yes, this will never return -32768 as an
238    immediate; this guaranteed that all signed immediates that are
239    return can have their sign inverted if need be.
240 */
241 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
242 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
243 
244 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
245    immediate in the range 1 .. 31 inclusive.  Used for doing shift amounts. */
246 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
247 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
248 
249 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
250    immediate in the range 1 .. 63 inclusive.  Used for doing shift amounts. */
251 static MIPSRH *iselWordExpr_RH6u_wrk(ISelEnv * env, IRExpr * e);
252 static MIPSRH *iselWordExpr_RH6u(ISelEnv * env, IRExpr * e);
253 
254 /* Compute an I8 into a reg-or-7-bit-unsigned-immediate, the latter being an
255    immediate in the range 1 .. 127 inclusive.  Used for doing shift amounts. */
256 static MIPSRH *iselWordExpr_RH7u_wrk(ISelEnv * env, IRExpr * e);
257 static MIPSRH *iselWordExpr_RH7u(ISelEnv * env, IRExpr * e);
258 
259 /* compute an I8/I16/I32 into a GPR*/
260 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e);
261 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e);
262 
263 /* compute an I32 into an AMode. */
264 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
265                                          IRType xferTy);
266 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy);
267 
268 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
269                               IRExpr * e);
270 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
271 
272 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
273 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo,
274                                ISelEnv * env, IRExpr * e);
275 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
276 
277 static HReg iselV128Expr( ISelEnv* env, IRExpr* e );
278 static HReg iselV128Expr_wrk( ISelEnv* env, IRExpr* e );
279 
280 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
281 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
282 
283 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
284 static HReg iselDblExpr(ISelEnv * env, IRExpr * e);
285 
286 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
287 static HReg iselFltExpr(ISelEnv * env, IRExpr * e);
288 
set_MIPS_rounding_mode(ISelEnv * env,IRExpr * mode)289 static void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
290 {
291    /*
292       rounding mode | MIPS | IR
293       ------------------------
294       to nearest    | 00  | 00
295       to zero       | 01  | 11
296       to +infinity  | 10  | 10
297       to -infinity  | 11  | 01
298     */
299    /* rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 3 */
300    HReg irrm = iselWordExpr_R(env, mode);
301    HReg tmp = newVRegI(env);
302    HReg fcsr_old = newVRegI(env);
303    MIPSAMode *am_addr;
304 
305    addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
306                                 MIPSRH_Imm(False, 1)));
307    addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
308    addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp, MIPSRH_Imm(False, 3)));
309    /* save old value of FCSR */
310    addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
311    sub_from_sp(env, 8); /*  Move SP down 8 bytes */
312    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
313 
314    /* store old FCSR to stack */
315    addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
316 
317    /* set new value of FCSR */
318    addInstr(env, MIPSInstr_MtFCSR(tmp));
319 }
320 
set_MIPS_rounding_mode_MSA(ISelEnv * env,IRExpr * mode)321 static void set_MIPS_rounding_mode_MSA(ISelEnv * env, IRExpr * mode) {
322    /*
323       rounding mode | MIPS | IR
324       ------------------------
325       to nearest    | 00  | 00
326       to zero       | 01  | 11
327       to +infinity  | 10  | 10
328       to -infinity  | 11  | 01
329     */
330    /* rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 3 */
331    HReg irrm = iselWordExpr_R(env, mode);
332    HReg tmp = newVRegI(env);
333    HReg msacsr_old = newVRegI(env);
334    MIPSAMode *am_addr;
335    addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
336                                 MIPSRH_Imm(False, 1)));
337    addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
338    addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp, MIPSRH_Imm(False, 3)));
339    /* save old value of MSACSR */
340    addInstr(env, MIPSInstr_MsaElm(MSA_CFCMSA, hregMIPS_GPR0(mode64), msacsr_old,
341                                   MSA_DFN_W));
342    sub_from_sp(env, 8); /*  Move SP down 8 bytes */
343    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
344    /* store old MSACSR to stack */
345    addInstr(env, MIPSInstr_Store(4, am_addr, msacsr_old, mode64));
346    /* set new value of MSACSR */
347    addInstr(env, MIPSInstr_MsaElm(MSA_CTCMSA, tmp, hregMIPS_GPR0(mode64),
348                                   MSA_DFN_W));
349 }
350 
351 
set_guest_MIPS_rounding_mode_MSA(ISelEnv * env)352 static void set_guest_MIPS_rounding_mode_MSA(ISelEnv * env) {
353    /*
354       rounding mode | MIPS | IR
355       ------------------------
356       to nearest    | 00  | 00
357       to zero       | 01  | 11
358       to +infinity  | 10  | 10
359       to -infinity  | 11  | 01
360     */
361    /* rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 3 */
362    HReg irrm =  newVRegI(env);
363    HReg msacsr_old = newVRegI(env);
364    MIPSAMode *am_addr;
365    MIPSAMode *rm_addr = MIPSAMode_IR(MSACSR_OFFSET(mode64),
366                                      GuestStatePointer(mode64));
367    addInstr(env, MIPSInstr_Load(4, irrm, rm_addr, mode64));
368    /* save old value of MSACSR */
369    addInstr(env, MIPSInstr_MsaElm(MSA_CFCMSA, hregMIPS_GPR0(mode64), msacsr_old,
370                                   MSA_DFN_W));
371    sub_from_sp(env, 8); /*  Move SP down 8 bytes */
372    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
373    /* store old MSACSR to stack */
374    addInstr(env, MIPSInstr_Store(4, am_addr, msacsr_old, mode64));
375    /* set new value of MSACSR */
376    addInstr(env, MIPSInstr_MsaElm(MSA_CTCMSA, irrm, hregMIPS_GPR0(mode64),
377                                   MSA_DFN_W));
378 }
379 
380 
set_MIPS_rounding_default(ISelEnv * env)381 static void set_MIPS_rounding_default(ISelEnv * env)
382 {
383    HReg fcsr = newVRegI(env);
384    /* load as float */
385    MIPSAMode *am_addr;
386    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
387 
388    addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
389 
390    add_to_sp(env, 8);  /* Reset SP */
391 
392    /* set new value of FCSR*/
393    addInstr(env, MIPSInstr_MtFCSR(fcsr));
394 }
395 
set_MIPS_rounding_default_MSA(ISelEnv * env)396 static void set_MIPS_rounding_default_MSA(ISelEnv * env) {
397    HReg msacsr = newVRegI(env);
398    /* load as float */
399    MIPSAMode *am_addr;
400    am_addr = MIPSAMode_IR(0, StackPointer(mode64));
401    addInstr(env, MIPSInstr_Load(4, msacsr, am_addr, mode64));
402    add_to_sp(env, 8);  /* Reset SP */
403    /* set new value of FCSR*/
404    addInstr(env, MIPSInstr_MsaElm(MSA_CTCMSA, msacsr, hregMIPS_GPR0(mode64),
405                                   MSA_DFN_W));
406 }
407 
408 /*---------------------------------------------------------*/
409 /*--- ISEL: Misc helpers                                ---*/
410 /*---------------------------------------------------------*/
411 
412 /* Make an int reg-reg move. */
mk_iMOVds_RR(HReg r_dst,HReg r_src)413 static MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
414 {
415    vassert(hregClass(r_dst) == hregClass(r_src));
416    vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
417    return MIPSInstr_Alu(Malu_OR, r_dst, r_src, MIPSRH_Reg(r_src));
418 }
419 
420 /*---------------------------------------------------------*/
421 /*--- ISEL: Function call helpers                       ---*/
422 /*---------------------------------------------------------*/
423 
424 /* Used only in doHelperCall.  See big comment in doHelperCall re
425    handling of register-parameter args.  This function figures out
426    whether evaluation of an expression might require use of a fixed
427    register.  If in doubt return True (safe but suboptimal).
428 */
mightRequireFixedRegs(IRExpr * e)429 static Bool mightRequireFixedRegs(IRExpr * e)
430 {
431    switch (e->tag) {
432       case Iex_RdTmp:
433       case Iex_Const:
434       case Iex_Get:
435          return False;
436       default:
437          return True;
438    }
439 }
440 
441 /* Load 2*I32 regs to fp reg */
mk_LoadRR32toFPR(ISelEnv * env,HReg r_srcHi,HReg r_srcLo)442 static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
443 {
444    HReg fr_dst = newVRegD(env);
445    MIPSAMode *am_addr0, *am_addr1;
446 
447    vassert(hregClass(r_srcHi) == HRcInt32);
448    vassert(hregClass(r_srcLo) == HRcInt32);
449 
450    sub_from_sp(env, 16);  /* Move SP down 16 bytes */
451    am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
452    am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
453 
454    /* store hi,lo as Ity_I32's */
455 #if defined (_MIPSEL)
456    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
457    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
458 #elif defined (_MIPSEB)
459    addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64));
460    addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64));
461 #else
462    /* Stop gcc on other platforms complaining about am_addr1 being set
463       but not used. */
464    (void)am_addr1;
465 #endif
466 
467    /* load as float */
468    addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
469 
470    add_to_sp(env, 16);  /* Reset SP */
471    return fr_dst;
472 }
473 
474 /* Do a complete function call.  |guard| is a Ity_Bit expression
475    indicating whether or not the call happens.  If guard==NULL, the
476    call is unconditional.  |retloc| is set to indicate where the
477    return value is after the call.  The caller (of this fn) must
478    generate code to add |stackAdjustAfterCall| to the stack pointer
479    after the call is done. */
480 
doHelperCall(UInt * stackAdjustAfterCall,RetLoc * retloc,ISelEnv * env,IRExpr * guard,IRCallee * cee,IRType retTy,IRExpr ** args)481 static void doHelperCall(/*OUT*/UInt*   stackAdjustAfterCall,
482                          /*OUT*/RetLoc* retloc,
483                          ISelEnv* env,
484                          IRExpr* guard,
485                          IRCallee* cee, IRType retTy, IRExpr** args )
486 {
487    MIPSCondCode cc;
488    HReg argregs[8];
489    HReg tmpregs[8];
490    Bool go_fast;
491    Int n_args, i, argreg;
492    UInt argiregs;
493    HReg src = INVALID_HREG;
494 
495    /* Set default returns.  We'll update them later if needed. */
496    *stackAdjustAfterCall = 0;
497    *retloc               = mk_RetLoc_INVALID();
498 
499    /* These are used for cross-checking that IR-level constraints on
500       the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
501    UInt nVECRETs = 0;
502    UInt nGSPTRs  = 0;
503 
504    /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
505       are allowed to be used for passing integer arguments. They correspond
506       to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
507       on MIPS host (since we only implement one calling convention) and so we
508       always ignore it. */
509 
510    /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
511       are allowed to be used for passing integer arguments. They correspond
512       to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
513       on MIPS host (since we only implement one calling convention) and so we
514       always ignore it. */
515 
516    /* The return type can be I{64,32,16,8} or V{128,256}.  In the
517       latter two cases, it is expected that |args| will contain the
518       special node IRExpr_VECRET(), in which case this routine
519       generates code to allocate space on the stack for the vector
520       return value.  Since we are not passing any scalars on the
521       stack, it is enough to preallocate the return space before
522       marshalling any arguments, in this case.
523 
524       |args| may also contain IRExpr_GSPTR(), in which case the value
525       in the guest state pointer register is passed as the
526       corresponding argument. */
527 
528    n_args = 0;
529    for (i = 0; args[i]; i++) {
530       IRExpr* arg = args[i];
531       if (UNLIKELY(arg->tag == Iex_VECRET)) {
532          nVECRETs++;
533       } else if (UNLIKELY(arg->tag == Iex_GSPTR)) {
534          nGSPTRs++;
535       }
536       n_args++;
537    }
538 
539    if (n_args > MIPS_N_REGPARMS) {
540       vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
541    }
542    if (mode64) {
543       argregs[0] = hregMIPS_GPR4(mode64);
544       argregs[1] = hregMIPS_GPR5(mode64);
545       argregs[2] = hregMIPS_GPR6(mode64);
546       argregs[3] = hregMIPS_GPR7(mode64);
547       argregs[4] = hregMIPS_GPR8(mode64);
548       argregs[5] = hregMIPS_GPR9(mode64);
549       argregs[6] = hregMIPS_GPR10(mode64);
550       argregs[7] = hregMIPS_GPR11(mode64);
551       argiregs = 0;
552       tmpregs[0] = tmpregs[1] = tmpregs[2] =
553       tmpregs[3] = tmpregs[4] = tmpregs[5] =
554       tmpregs[6] = tmpregs[7] = INVALID_HREG;
555    } else {
556       argregs[0] = hregMIPS_GPR4(mode64);
557       argregs[1] = hregMIPS_GPR5(mode64);
558       argregs[2] = hregMIPS_GPR6(mode64);
559       argregs[3] = hregMIPS_GPR7(mode64);
560       argiregs = 0;
561       tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
562    }
563 
564    /* First decide which scheme (slow or fast) is to be used. First assume the
565       fast scheme, and select slow if any contraindications (wow) appear. */
566 
567    go_fast = True;
568 
569    /* We'll need space on the stack for the return value.  Avoid
570       possible complications with nested calls by using the slow
571       scheme. */
572    if (retTy == Ity_V128 || retTy == Ity_V256)
573       go_fast = False;
574 
575    if (go_fast && guard) {
576       if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
577           && guard->Iex.Const.con->Ico.U1 == True) {
578          /* unconditional */
579       } else {
580          /* Not manifestly unconditional -- be conservative. */
581          go_fast = False;
582       }
583    }
584 
585    if (go_fast) {
586       for (i = 0; i < n_args; i++) {
587          if (mightRequireFixedRegs(args[i])) {
588             go_fast = False;
589             break;
590          }
591       }
592    }
593 
594    /* At this point the scheme to use has been established.  Generate
595       code to get the arg values into the argument rregs. */
596    if (go_fast) {
597       /* FAST SCHEME */
598       argreg = 0;
599 
600       for (i = 0; i < n_args; i++) {
601          IRExpr* arg = args[i];
602          vassert(argreg < MIPS_N_REGPARMS);
603 
604          IRType  aTy = Ity_INVALID;
605          if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
606             aTy = typeOfIRExpr(env->type_env, arg);
607 
608          if (aTy == Ity_I32 || (mode64 && aTy != Ity_INVALID)) {
609             argiregs |= (1 << (argreg + 4));
610             addInstr(env, mk_iMOVds_RR(argregs[argreg],
611                                        iselWordExpr_R(env, arg)));
612             argreg++;
613          } else if (aTy == Ity_I64) {  /* Ity_I64 */
614             if (argreg & 1) {
615                argreg++;
616                argiregs |= (1 << (argreg + 4));
617             }
618             HReg rHi, rLo;
619             iselInt64Expr(&rHi, &rLo, env, arg);
620             argiregs |= (1 << (argreg + 4));
621             addInstr(env, mk_iMOVds_RR( argregs[argreg++], rLo ));
622             argiregs |= (1 << (argreg + 4));
623             addInstr(env, mk_iMOVds_RR( argregs[argreg], rHi));
624             argreg++;
625          } else if (arg->tag == Iex_GSPTR) {
626             vassert(0);  // ATC
627             addInstr(env, mk_iMOVds_RR(argregs[argreg],
628                                        GuestStatePointer(mode64)));
629             argreg++;
630          } else if (arg->tag == Iex_VECRET) {
631             // If this happens, it denotes ill-formed IR.
632             vassert(0);
633          }
634       }
635       /* Fast scheme only applies for unconditional calls.  Hence: */
636       cc = MIPScc_AL;
637    } else {
638       /* SLOW SCHEME; move via temporaries */
639       argreg = 0;
640 
641       for (i = 0; i < n_args; i++) {
642          vassert(argreg < MIPS_N_REGPARMS);
643          IRExpr* arg = args[i];
644 
645          IRType  aTy = Ity_INVALID;
646          if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
647             aTy  = typeOfIRExpr(env->type_env, arg);
648 
649          if (aTy == Ity_I32 || (mode64 && aTy != Ity_INVALID)) {
650             tmpregs[argreg] = iselWordExpr_R(env, arg);
651             argreg++;
652          } else if (aTy == Ity_I64) {  /* Ity_I64 */
653             if (argreg & 1)
654                argreg++;
655             if (argreg + 1 >= MIPS_N_REGPARMS)
656                vassert(0);  /* out of argregs */
657             HReg raHi, raLo;
658             iselInt64Expr(&raHi, &raLo, env, arg);
659             tmpregs[argreg] = raLo;
660             argreg++;
661             tmpregs[argreg] = raHi;
662             argreg++;
663          } else if (arg->tag == Iex_GSPTR) {
664             tmpregs[argreg] = GuestStatePointer(mode64);
665             argreg++;
666          }
667          else if (arg->tag == Iex_VECRET) {
668             tmpregs[argreg++] = StackPointer(mode64);
669             sub_from_sp(env, 16); /*  Move SP down 16 bytes */
670          }
671       }
672 
673       /* Now we can compute the condition.  We can't do it earlier
674          because the argument computations could trash the condition
675          codes.  Be a bit clever to handle the common case where the
676          guard is 1:Bit. */
677       cc = MIPScc_AL;
678       if (guard) {
679          if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
680              && guard->Iex.Const.con->Ico.U1 == True) {
681             /* unconditional -- do nothing */
682          } else {
683             cc = iselCondCode(env, guard);
684             src = iselWordExpr_R(env, guard);
685          }
686       }
687       /* Move the args to their final destinations. */
688       for (i = 0; i < argreg; i++) {
689          if (hregIsInvalid(tmpregs[i]))  /* Skip invalid regs */
690             continue;
691          /* None of these insns, including any spill code that might
692             be generated, may alter the condition codes. */
693          argiregs |= (1 << (i + 4));
694          addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
695       }
696    }
697 
698    /* Do final checks, set the return values, and generate the call
699       instruction proper. */
700    vassert(nGSPTRs == 0 || nGSPTRs == 1);
701    vassert(nVECRETs == ((retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0));
702    vassert(*stackAdjustAfterCall == 0);
703    vassert(is_RetLoc_INVALID(*retloc));
704    switch (retTy) {
705       case Ity_INVALID:
706          /* Function doesn't return a value. */
707          *retloc = mk_RetLoc_simple(RLPri_None);
708          break;
709       case Ity_I64:
710          *retloc = mk_RetLoc_simple(mode64 ? RLPri_Int : RLPri_2Int);
711          break;
712       case Ity_I32: case Ity_I16: case Ity_I8:
713          *retloc = mk_RetLoc_simple(RLPri_Int);
714          break;
715       case Ity_V128:
716          *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0);
717          *stackAdjustAfterCall = 16;
718          break;
719       case Ity_V256:
720          vassert(0); // ATC
721          *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0);
722          *stackAdjustAfterCall = 32;
723          break;
724       default:
725          /* IR can denote other possible return types, but we don't
726             handle those here. */
727         vassert(0);
728    }
729 
730    Addr64 target = mode64 ? (Addr)cee->addr :
731                             toUInt((Addr)cee->addr);
732 
733    /* Finally, generate the call itself.  This needs the *retloc value
734       set in the switch above, which is why it's at the end. */
735    if (cc == MIPScc_AL)
736       addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs,
737                                          *retloc));
738    else
739       addInstr(env, MIPSInstr_Call(cc, target, argiregs, src, *retloc));
740 }
741 
742 /*---------------------------------------------------------*/
743 /*--- ISEL: Integer expression auxiliaries              ---*/
744 /*---------------------------------------------------------*/
745 
746 /* --------------------- AMODEs --------------------- */
747 
748 /* Return an AMode which computes the value of the specified
749    expression, possibly also adding insns to the code list as a
750    result.  The expression may only be a word-size one.
751 */
752 
uInt_fits_in_16_bits(UInt u)753 static Bool uInt_fits_in_16_bits(UInt u)
754 {
755    Int i = u & 0xFFFF;
756    i <<= 16;
757    i >>= 16;
758    return toBool(u == (UInt) i);
759 }
760 
uLong_fits_in_16_bits(ULong u)761 static Bool uLong_fits_in_16_bits ( ULong u )
762 {
763    Long i = u & 0xFFFFULL;
764    i <<= 48;
765    i >>= 48;
766    return toBool(u == (ULong) i);
767 }
768 
uLong_is_4_aligned(ULong u)769 static Bool uLong_is_4_aligned ( ULong u )
770 {
771    return toBool((u & 3ULL) == 0);
772 }
773 
sane_AMode(ISelEnv * env,MIPSAMode * am)774 static Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
775 {
776    switch (am->tag) {
777       case Mam_IR:
778          return toBool(hregClass(am->Mam.IR.base) == HRcGPR(mode64) &&
779                   hregIsVirtual(am->Mam.IR.base) &&
780                   uInt_fits_in_16_bits(am->Mam.IR.index));
781       case Mam_RR:
782          return toBool(hregClass(am->Mam.RR.base) == HRcGPR(mode64) &&
783                   hregIsVirtual(am->Mam.RR.base) &&
784                   hregClass(am->Mam.RR.index) == HRcGPR(mode64) &&
785                   hregIsVirtual(am->Mam.RR.index));
786       default:
787          vpanic("sane_AMode: unknown mips amode tag");
788    }
789 }
790 
iselWordExpr_AMode(ISelEnv * env,IRExpr * e,IRType xferTy)791 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
792 {
793    MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
794    vassert(sane_AMode(env, am));
795    return am;
796 }
797 
798 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_AMode_wrk(ISelEnv * env,IRExpr * e,IRType xferTy)799 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
800                                          IRType xferTy)
801 {
802    IRType ty = typeOfIRExpr(env->type_env, e);
803    if (env->mode64) {
804       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
805       vassert(ty == Ity_I64);
806 
807       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
808       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64
809           && e->Iex.Binop.arg2->tag == Iex_Const
810           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
811           && (aligned4imm ?
812           uLong_is_4_aligned(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64) : True)
813           && uLong_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
814          return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
815                                    iselWordExpr_R(env, e->Iex.Binop.arg1));
816       }
817 
818       /* Add64(expr,expr) */
819       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64) {
820          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
821          HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
822          return MIPSAMode_RR(r_idx, r_base);
823       }
824    } else {
825       vassert(ty == Ity_I32);
826 
827       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
828       if (e->tag == Iex_Binop
829           && e->Iex.Binop.op == Iop_Add32
830           && e->Iex.Binop.arg2->tag == Iex_Const
831           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
832           && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con-> Ico.U32)) {
833          return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
834                               iselWordExpr_R(env, e->Iex.Binop.arg1));
835       }
836 
837       /* Add32(expr,expr) */
838       if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) {
839          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
840          HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
841 
842          return MIPSAMode_RR(r_idx, r_base);
843       }
844    }
845 
846    /* Doesn't match anything in particular.  Generate it into
847       a register and use that. */
848    return MIPSAMode_IR(0, iselWordExpr_R(env, e));
849 }
850 
851 /*---------------------------------------------------------*/
852 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
853 /*---------------------------------------------------------*/
854 
855 /* Select insns for an integer-typed expression, and add them to the
856    code list.  Return a reg holding the result.  This reg will be a
857    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
858    want to modify it, ask for a new vreg, copy it in there, and modify
859    the copy.  The register allocator will do its best to map both
860    vregs to the same real register, so the copies will often disappear
861    later in the game.
862 
863    This should handle expressions of 64, 32, 16 and 8-bit type.
864    All results are returned in a (mode64 ? 64bit : 32bit) register.
865    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
866    are arbitrary, so you should mask or sign extend partial values
867    if necessary.
868 */
iselWordExpr_R(ISelEnv * env,IRExpr * e)869 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
870 {
871    HReg r = iselWordExpr_R_wrk(env, e);
872    /* sanity checks ... */
873 
874    vassert(hregClass(r) == HRcGPR(env->mode64));
875    vassert(hregIsVirtual(r));
876    return r;
877 }
878 
879 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_R_wrk(ISelEnv * env,IRExpr * e)880 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
881 {
882    UInt argiregs = 0;
883    IRType ty = typeOfIRExpr(env->type_env, e);
884    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1
885            || ty == Ity_F32 || (ty == Ity_I64 && mode64)
886            || (ty == Ity_I128 && mode64));
887 
888    switch (e->tag) {
889       /* --------- TEMP --------- */
890       case Iex_RdTmp:
891          return lookupIRTemp(env, e->Iex.RdTmp.tmp);
892 
893       /* --------- LOAD --------- */
894       case Iex_Load: {
895          HReg r_dst = newVRegI(env);
896          MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
897 
898          if (e->Iex.Load.end != Iend_LE
899              && e->Iex.Load.end != Iend_BE)
900             goto irreducible;
901 
902          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
903                                       r_dst, am_addr, mode64));
904          return r_dst;
905       }
906 
907       /* --------- BINARY OP --------- */
908       case Iex_Binop: {
909          MIPSAluOp aluOp;
910          MIPSShftOp shftOp;
911 
912          /* Is it an addition or logical style op? */
913          switch (e->Iex.Binop.op) {
914             case Iop_Add8:
915             case Iop_Add16:
916             case Iop_Add32:
917                aluOp = Malu_ADD;
918                break;
919 
920             case Iop_Sub8:
921             case Iop_Sub16:
922             case Iop_Sub32:
923                aluOp = Malu_SUB;
924                break;
925 
926             case Iop_Sub64:
927                aluOp = Malu_DSUB;
928                break;
929 
930             case Iop_And8:
931             case Iop_And16:
932             case Iop_And32:
933             case Iop_And64:
934                aluOp = Malu_AND;
935                break;
936 
937             case Iop_Or8:
938             case Iop_Or16:
939             case Iop_Or32:
940             case Iop_Or64:
941                aluOp = Malu_OR;
942                break;
943 
944             case Iop_Xor8:
945             case Iop_Xor16:
946             case Iop_Xor32:
947             case Iop_Xor64:
948                aluOp = Malu_XOR;
949                break;
950 
951             case Iop_Add64:
952                aluOp = Malu_DADD;
953                break;
954 
955             default:
956                aluOp = Malu_INVALID;
957                break;
958          }
959 
960          /* For commutative ops we assume any literal
961             values are on the second operand. */
962          if (aluOp != Malu_INVALID) {
963             HReg r_dst = newVRegI(env);
964             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
965             MIPSRH *ri_srcR = NULL;
966             /* get right arg into an RH, in the appropriate way */
967             switch (aluOp) {
968                case Malu_ADD:
969                case Malu_SUB:
970                case Malu_DADD:
971                case Malu_DSUB:
972                   ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
973                                             e->Iex.Binop.arg2);
974                   break;
975                case Malu_AND:
976                case Malu_OR:
977                case Malu_XOR:
978                   ri_srcR = iselWordExpr_RH(env, False /*unsigned */,
979                                             e->Iex.Binop.arg2);
980                   break;
981                default:
982                   vpanic("iselWordExpr_R_wrk-aluOp-arg2");
983             }
984             addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
985             return r_dst;
986          }
987 
988          /* a shift? */
989          switch (e->Iex.Binop.op) {
990             case Iop_Shl32:
991             case Iop_Shl64:
992                shftOp = Mshft_SLL;
993                break;
994             case Iop_Shr16:
995             case Iop_Shr32:
996             case Iop_Shr64:
997                shftOp = Mshft_SRL;
998                break;
999             case Iop_Sar16:
1000             case Iop_Sar32:
1001             case Iop_Sar64:
1002                shftOp = Mshft_SRA;
1003                break;
1004             default:
1005                shftOp = Mshft_INVALID;
1006                break;
1007          }
1008 
1009          /* we assume any literal values are on the second operand. */
1010          if (shftOp != Mshft_INVALID) {
1011             HReg r_dst = newVRegI(env);
1012             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1013             MIPSRH *ri_srcR;
1014             if (mode64)
1015                ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
1016             else
1017                ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
1018 
1019             if (ty == Ity_I8) {
1020                vassert(0);
1021             } else if (ty == Ity_I16) {
1022                if (shftOp == Mshft_SRA) {
1023                   HReg tmp = newVRegI(env);
1024                   HReg r_srcL_se = newVRegI(env);
1025                   addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp,
1026                                                r_srcL, MIPSRH_Imm(False, 16)));
1027                   addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_srcL_se,
1028                                                tmp, MIPSRH_Imm(False, 16)));
1029                   addInstr(env, MIPSInstr_Shft(shftOp, True,
1030                                                r_dst, r_srcL_se, ri_srcR));
1031                } else if (shftOp == Mshft_SRL) {
1032                   HReg r_srcL_se = newVRegI(env);
1033                   addInstr(env, MIPSInstr_Alu(Malu_AND, r_srcL_se, r_srcL,
1034                                               MIPSRH_Imm(False, 0xFFFF)));
1035                   addInstr(env, MIPSInstr_Shft(shftOp, True,
1036                                                r_dst, r_srcL_se, ri_srcR));
1037                } else {
1038                   vassert(0);
1039                }
1040             } else if (ty == Ity_I32) {
1041                if (mode64 && (shftOp == Mshft_SRA || shftOp == Mshft_SRL)) {
1042                   HReg tmp = newVRegI(env);
1043                   HReg r_srcL_se = newVRegI(env);
1044                   /* SRA, SRAV, SRL, SRLV: On 64-bit processors, if GPR rt does
1045                      not contain a sign-extended 32-bit value (bits 63..31
1046                      equal), then the result of the operation is UNPREDICTABLE.
1047                      So we need to sign-extend r_srcL:
1048                      DSLLV tmp, r_srcL, 32
1049                      DSRAV r_srcL_se, tmp, 32
1050                   */
1051                   addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tmp,
1052                                                r_srcL, MIPSRH_Imm(False, 32)));
1053                   addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, r_srcL_se,
1054                                                tmp, MIPSRH_Imm(False, 32)));
1055                   /* And finally do the shift. */
1056                   addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
1057                                                r_dst, r_srcL_se, ri_srcR));
1058                } else
1059                   addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
1060                                                r_dst, r_srcL, ri_srcR));
1061             } else if (ty == Ity_I64) {
1062                vassert(mode64);
1063                addInstr(env, MIPSInstr_Shft(shftOp, False/*64bit shift */,
1064                                             r_dst, r_srcL, ri_srcR));
1065             } else
1066                goto irreducible;
1067             return r_dst;
1068          }
1069 
1070           if (!mode64 && (e->Iex.Binop.op == Iop_CasCmpEQ64
1071               || e->Iex.Binop.op == Iop_CmpEQ64)) {
1072              HReg tmp1, tmp2, tmp3, tmp4;
1073              HReg dst1 = newVRegI(env);
1074              HReg dst2 = newVRegI(env);
1075              iselInt64Expr(&tmp1, &tmp2, env, e->Iex.Binop.arg1);
1076              iselInt64Expr(&tmp3, &tmp4, env, e->Iex.Binop.arg2);
1077              addInstr(env, MIPSInstr_Cmp(False, True, dst1, tmp1, tmp3, MIPScc_EQ));
1078              addInstr(env, MIPSInstr_Cmp(False, True, dst2, tmp2, tmp4, MIPScc_EQ));
1079              addInstr(env, MIPSInstr_Alu(Malu_AND, dst1, dst1, MIPSRH_Reg(dst2)));
1080              return dst1;
1081           }
1082 
1083          /* Cmp*32*(x,y) ? */
1084          if (e->Iex.Binop.op == Iop_CmpEQ32
1085              || e->Iex.Binop.op == Iop_CmpEQ8
1086              || e->Iex.Binop.op == Iop_CmpEQ16
1087              || e->Iex.Binop.op == Iop_CmpNE32
1088              || e->Iex.Binop.op == Iop_CmpNE64
1089              || e->Iex.Binop.op == Iop_CmpLT32S
1090              || e->Iex.Binop.op == Iop_CmpLT32U
1091              || e->Iex.Binop.op == Iop_CmpLT64U
1092              || e->Iex.Binop.op == Iop_CmpLE32U
1093              || e->Iex.Binop.op == Iop_CmpLE32S
1094              || e->Iex.Binop.op == Iop_CmpLE64S
1095              || e->Iex.Binop.op == Iop_CmpLT64S
1096              || e->Iex.Binop.op == Iop_CmpEQ64
1097              || e->Iex.Binop.op == Iop_CasCmpEQ32
1098              || e->Iex.Binop.op == Iop_CasCmpEQ64) {
1099 
1100             Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
1101                          || e->Iex.Binop.op == Iop_CmpLE32S
1102                          || e->Iex.Binop.op == Iop_CmpLT64S
1103                          || e->Iex.Binop.op == Iop_CmpLE64S);
1104             Bool size32;
1105             HReg dst = newVRegI(env);
1106             HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
1107             HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
1108 
1109             MIPSCondCode cc;
1110 
1111             switch (e->Iex.Binop.op) {
1112                case Iop_CmpEQ32:
1113                case Iop_CasCmpEQ32:
1114                   cc = MIPScc_EQ;
1115                   size32 = True;
1116                   break;
1117                case Iop_CmpEQ8:
1118                case Iop_CmpEQ16:
1119                   cc = MIPScc_EQ;
1120                   size32 = True;
1121                   break;
1122                case Iop_CmpNE32:
1123                   cc = MIPScc_NE;
1124                   size32 = True;
1125                   break;
1126                case Iop_CmpNE64:
1127                   cc = MIPScc_NE;
1128                   size32 = False;
1129                   break;
1130                case Iop_CmpLT32S:
1131                   cc = MIPScc_LT;
1132                   size32 = True;
1133                   break;
1134                case Iop_CmpLT32U:
1135                   cc = MIPScc_LO;
1136                   size32 = True;
1137                   break;
1138                case Iop_CmpLT64U:
1139                   cc = MIPScc_LO;
1140                   size32 = False;
1141                   break;
1142                case Iop_CmpLE32U:
1143                   cc = MIPScc_LE;
1144                   size32 = True;
1145                   break;
1146                case Iop_CmpLE32S:
1147                   cc = MIPScc_LE;
1148                   size32 = True;
1149                   break;
1150                case Iop_CmpLE64S:
1151                   cc = MIPScc_LE;
1152                   size32 = False;
1153                   break;
1154                case Iop_CmpLT64S:
1155                   cc = MIPScc_LT;
1156                   size32 = False;
1157                   break;
1158                case Iop_CmpEQ64:
1159                case Iop_CasCmpEQ64:
1160                   cc = MIPScc_EQ;
1161                   size32 = False;
1162                   break;
1163                default:
1164                   vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
1165             }
1166 
1167             addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
1168             return dst;
1169          }
1170 
1171          if (e->Iex.Binop.op == Iop_Max32U) {
1172             HReg tmp = newVRegI(env);
1173             HReg r_dst = newVRegI(env);
1174             HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1175             HReg argR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1176             MIPSRH *argRH = MIPSRH_Reg(argR);
1177             /* max (v0, s0)
1178                ------------
1179                slt v1, v0, s0
1180                movn v0, s0, v1 */
1181 
1182             addInstr(env, MIPSInstr_Alu(Malu_SLT, tmp, argL, argRH));
1183 #if (__mips_isa_rev >= 6)
1184             {
1185               HReg r_temp  = newVRegI(env);
1186               addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dst, argL, tmp));
1187               addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, argR, tmp));
1188               addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
1189                                 MIPSRH_Reg(r_temp)));
1190             }
1191 
1192 #else
1193             addInstr(env, mk_iMOVds_RR(r_dst, argL));
1194             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, argR, tmp));
1195 #endif
1196             return r_dst;
1197          }
1198 
1199          if (e->Iex.Binop.op == Iop_Mul32) {
1200             HReg r_dst = newVRegI(env);
1201             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1202             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1203 #if (__mips_isa_rev >= 6)
1204             addInstr(env, MIPSInstr_Mulr6(False, True, True,
1205                                           r_dst, r_srcL, r_srcR));
1206 #else
1207             addInstr(env, MIPSInstr_Mul(r_dst, r_srcL, r_srcR));
1208 #endif
1209             return r_dst;
1210          }
1211 
1212          if (e->Iex.Binop.op == Iop_Mul64 ||
1213              e->Iex.Binop.op == Iop_MullS32) {
1214             vassert(mode64);
1215             HReg r_dst = newVRegI(env);
1216             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1217             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1218 #if (__mips_isa_rev >= 6)
1219             addInstr(env, MIPSInstr_Mulr6(False, False, True,
1220                                           r_dst, r_srcL, r_srcR));
1221 #else
1222             addInstr(env, MIPSInstr_Mult(True, r_srcL, r_srcR));
1223             addInstr(env, MIPSInstr_Mflo(r_dst));
1224 #endif
1225             return r_dst;
1226          }
1227 
1228          if (e->Iex.Binop.op == Iop_MullU32) {
1229             vassert(mode64);
1230             HReg r_tmpL = newVRegI(env);
1231             HReg r_tmpR = newVRegI(env);
1232             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1233             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1234 #if (__mips_isa_rev >= 6)
1235             addInstr(env, MIPSInstr_Ext(r_tmpL, r_srcL, 0, 32));
1236             addInstr(env, MIPSInstr_Ext(r_tmpR, r_srcR, 0, 32));
1237             addInstr(env, MIPSInstr_Mulr6(True, False, True,
1238                                           r_tmpR, r_tmpL, r_tmpR));
1239 #else
1240             if (VEX_MIPS_CPU_HAS_MIPS64R2(hwcaps_host)) {
1241                addInstr(env, MIPSInstr_Ext(r_tmpL, r_srcL, 0, 32));
1242                addInstr(env, MIPSInstr_Ext(r_tmpR, r_srcR, 0, 32));
1243             } else {
1244                addInstr(env, MIPSInstr_LI(r_tmpL, 0xFFFFFFFF));
1245                addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmpR, r_srcR,
1246                                            MIPSRH_Reg(r_tmpL)));
1247                addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmpL, r_srcL,
1248                                            MIPSRH_Reg(r_tmpL)));
1249             }
1250             addInstr(env, MIPSInstr_Mult(False, r_tmpL, r_tmpR));
1251             addInstr(env, MIPSInstr_Mflo(r_tmpR));
1252 #endif
1253             return r_tmpR;
1254          }
1255 
1256          if (e->Iex.Binop.op == Iop_MullU8 ||
1257              e->Iex.Binop.op == Iop_MullS8 ||
1258              e->Iex.Binop.op == Iop_MullU16 ||
1259              e->Iex.Binop.op == Iop_MullS16) {
1260             Bool syned = toBool((e->Iex.Binop.op == Iop_MullS8) ||
1261                                 (e->Iex.Binop.op == Iop_MullS16));
1262             HReg r_dst = newVRegI(env);
1263             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1264             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1265 #if (__mips_isa_rev >= 6)
1266              if (syned) {
1267                Int no_bits = (e->Iex.Binop.op == Iop_MullS16) ? 16 : 24;
1268                addInstr(env, MIPSInstr_Shft(Mshft_SLL, True,
1269                                             r_srcL, r_srcL,
1270                                             MIPSRH_Imm(False, no_bits)));
1271                addInstr(env, MIPSInstr_Shft(Mshft_SRA, True,
1272                                             r_srcL, r_srcL,
1273                                             MIPSRH_Imm(False, no_bits)));
1274                addInstr(env, MIPSInstr_Shft(Mshft_SLL, True,
1275                                             r_srcR, r_srcR,
1276                                             MIPSRH_Imm(False, no_bits)));
1277                addInstr(env, MIPSInstr_Shft(Mshft_SRA, True,
1278                                             r_srcR, r_srcR,
1279                                             MIPSRH_Imm(False, no_bits)));
1280             }
1281             addInstr(env, MIPSInstr_Mulr6(syned, True, True,
1282                                           r_dst, r_srcL, r_srcR));
1283 #else
1284             if (syned) {
1285                Int no_bits = (e->Iex.Binop.op == Iop_MullS16) ? 16 : 24;
1286                addInstr(env, MIPSInstr_Shft(Mshft_SLL, True,
1287                                             r_srcL, r_srcL,
1288                                             MIPSRH_Imm(False, no_bits)));
1289                addInstr(env, MIPSInstr_Shft(Mshft_SRA, True,
1290                                             r_srcL, r_srcL,
1291                                             MIPSRH_Imm(False, no_bits)));
1292                addInstr(env, MIPSInstr_Shft(Mshft_SLL, True,
1293                                             r_srcR, r_srcR,
1294                                             MIPSRH_Imm(False, no_bits)));
1295                addInstr(env, MIPSInstr_Shft(Mshft_SRA, True,
1296                                             r_srcR, r_srcR,
1297                                             MIPSRH_Imm(False, no_bits)));
1298                addInstr(env, MIPSInstr_Mul(r_dst, r_srcL, r_srcR));
1299 
1300             } else {
1301                addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
1302                addInstr(env, MIPSInstr_Mflo(r_dst));
1303             }
1304 #endif
1305             return r_dst;
1306          }
1307 
1308          if (e->Iex.Binop.op == Iop_CmpF64) {
1309             HReg r_srcL, r_srcR;
1310             if (mode64) {
1311                r_srcL = iselFltExpr(env, e->Iex.Binop.arg1);
1312                r_srcR = iselFltExpr(env, e->Iex.Binop.arg2);
1313             } else {
1314                r_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
1315                r_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
1316             }
1317 #if (__mips_isa_rev >= 6)
1318             HReg tmp = newVRegI(env);
1319             HReg tmpf;
1320             HReg result = newVRegI(env);
1321             if (mode64) tmpf = newVRegF(env);
1322             else tmpf = newVRegD(env);
1323             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN, tmpf, r_srcL, r_srcR));
1324             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1325             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1326                                         MIPSRH_Imm(False, 0x45)));
1327             addInstr(env, MIPSInstr_Alu(Malu_OR, result,
1328                                         hregMIPS_GPR0(env->mode64),
1329                                         MIPSRH_Reg(tmp)));
1330             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT, tmpf, r_srcL, r_srcR));
1331             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1332             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1333                                         MIPSRH_Imm(False, 0x1)));
1334             addInstr(env, MIPSInstr_Alu(Malu_OR, result, result,
1335                                         MIPSRH_Reg(tmp)));
1336             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ, tmpf, r_srcL, r_srcR));
1337             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1338             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1339                                         MIPSRH_Imm(False, 0x40)));
1340             addInstr(env, MIPSInstr_Alu(Malu_OR, result, result,
1341                                         MIPSRH_Reg(tmp)));
1342             return result;
1343 #else
1344             HReg tmp = newVRegI(env);
1345             HReg r_ccMIPS = newVRegI(env);
1346             HReg r_ccIR = newVRegI(env);
1347             HReg r_ccIR_b0 = newVRegI(env);
1348             HReg r_ccIR_b2 = newVRegI(env);
1349             HReg r_ccIR_b6 = newVRegI(env);
1350 
1351             /* Create in dst, the IRCmpF64Result encoded result. */
1352             /* chech for EQ */
1353             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ, tmp, r_srcL, r_srcR));
1354             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccMIPS, tmp,
1355                                          MIPSRH_Imm(False, 1)));
1356             /* chech for UN */
1357             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN, tmp, r_srcL, r_srcR));
1358             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1359                                         MIPSRH_Reg(tmp)));
1360             /* chech for LT */
1361             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT, tmp, r_srcL, r_srcR));
1362             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp,
1363                                          tmp, MIPSRH_Imm(False, 2)));
1364             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1365                                         MIPSRH_Reg(tmp)));
1366             /* chech for GT */
1367             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_NGT,
1368                                               tmp, r_srcL, r_srcR));
1369             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, tmp,
1370                                          MIPSRH_Imm(False, 3)));
1371 
1372             addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
1373             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1374                                         MIPSRH_Imm(False, 8)));
1375             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1376                                         MIPSRH_Reg(tmp)));
1377             /* Map compare result from MIPS to IR,
1378                conforming to CmpF64 definition.
1379                FP cmp result | MIPS | IR
1380                --------------------------
1381                UN            | 0x1 | 0x45
1382                EQ            | 0x2 | 0x40
1383                GT            | 0x4 | 0x00
1384                LT            | 0x8 | 0x01
1385              */
1386 
1387             /* r_ccIR_b0 = r_ccMIPS[0] | r_ccMIPS[3] */
1388             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b0, r_ccMIPS,
1389                           MIPSRH_Imm(False, 0x3)));
1390             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b0, r_ccMIPS,
1391                           MIPSRH_Reg(r_ccIR_b0)));
1392             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b0, r_ccIR_b0,
1393                           MIPSRH_Imm(False, 0x1)));
1394 
1395             /* r_ccIR_b2 = r_ccMIPS[0] */
1396             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b2, r_ccMIPS,
1397                           MIPSRH_Imm(False, 0x2)));
1398             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b2, r_ccIR_b2,
1399                           MIPSRH_Imm(False, 0x4)));
1400 
1401             /* r_ccIR_b6 = r_ccMIPS[0] | r_ccMIPS[1] */
1402             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b6,
1403                           r_ccMIPS, MIPSRH_Imm(False, 0x1)));
1404             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b6, r_ccMIPS,
1405                           MIPSRH_Reg(r_ccIR_b6)));
1406             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b6, r_ccIR_b6,
1407                           MIPSRH_Imm(False, 0x6)));
1408             addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b6, r_ccIR_b6,
1409                           MIPSRH_Imm(False, 0x40)));
1410 
1411             /* r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 */
1412             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR_b0,
1413                           MIPSRH_Reg(r_ccIR_b2)));
1414             addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR,
1415                           MIPSRH_Reg(r_ccIR_b6)));
1416             return r_ccIR;
1417 #endif
1418          }
1419 
1420          if (e->Iex.Binop.op == Iop_CmpF32) {
1421 #if (__mips_isa_rev >= 6)
1422             HReg r_srcL = iselFltExpr(env, e->Iex.Binop.arg1);
1423             HReg r_srcR = iselFltExpr(env, e->Iex.Binop.arg2);
1424             HReg tmp = newVRegI(env);
1425             HReg tmpf;
1426             HReg result = newVRegI(env);
1427             if (mode64) tmpf = newVRegF(env);
1428             else tmpf = newVRegD(env);
1429             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN_S, tmpf, r_srcL, r_srcR));
1430             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1431             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1432                                         MIPSRH_Imm(False, 0x45)));
1433             addInstr(env, MIPSInstr_Alu(Malu_OR, result,
1434                                         hregMIPS_GPR0(env->mode64),
1435                                         MIPSRH_Reg(tmp)));
1436             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT_S, tmpf, r_srcL, r_srcR));
1437             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1438             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1439                                         MIPSRH_Imm(False, 0x1)));
1440             addInstr(env, MIPSInstr_Alu(Malu_OR, result, result,
1441                                         MIPSRH_Reg(tmp)));
1442             addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ_S, tmpf, r_srcL, r_srcR));
1443             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, tmp, tmpf));
1444             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1445                                         MIPSRH_Imm(False, 0x40)));
1446             addInstr(env, MIPSInstr_Alu(Malu_OR, result, result,
1447                                         MIPSRH_Reg(tmp)));
1448             return result;
1449 #endif
1450          }
1451 
1452          if (e->Iex.Binop.op == Iop_DivModU32to32 ||
1453              e->Iex.Binop.op == Iop_DivModS32to32) {
1454             HReg tLo = newVRegI(env);
1455             HReg tHi = newVRegI(env);
1456             HReg mask = newVRegI(env);
1457             HReg tLo_1 = newVRegI(env);
1458             HReg tHi_1 = newVRegI(env);
1459             HReg r_dst = newVRegI(env);
1460             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS32to32);
1461 
1462             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1463             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1464 #if (__mips_isa_rev >= 6)
1465             addInstr(env, MIPSInstr_Divr6(syned /* Unsigned or Signed */ ,
1466                                           True  /* 32bit or 64bit div */ ,
1467                                           False /* mod */,
1468                                           tLo, r_srcL, r_srcR));
1469             addInstr(env, MIPSInstr_Divr6(syned /* Unsigned or Signed */ ,
1470                                           True /*3 2bit or 64bit div */ ,
1471                                           True /* mod */,
1472                                           tHi, r_srcL, r_srcR));
1473 #else
1474             addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
1475             addInstr(env, MIPSInstr_Mfhi(tHi));
1476             addInstr(env, MIPSInstr_Mflo(tLo));
1477 #endif
1478             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
1479                                          MIPSRH_Imm(False, 32)));
1480 
1481             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1482             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1483                           MIPSRH_Reg(mask)));
1484 
1485             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1486                           MIPSRH_Reg(tLo_1)));
1487 
1488             return r_dst;
1489          }
1490 
1491          if (e->Iex.Binop.op == Iop_DivS32 ||
1492              e->Iex.Binop.op == Iop_DivU32 ||
1493              (e->Iex.Binop.op == Iop_DivS64 && mode64) ||
1494              (e->Iex.Binop.op == Iop_DivU64 && mode64)) {
1495             HReg r_dst = newVRegI(env);
1496             Bool syned = toBool(e->Iex.Binop.op == Iop_DivS32 ||
1497                                 e->Iex.Binop.op == Iop_DivS64);
1498             Bool div32 = toBool(e->Iex.Binop.op == Iop_DivS32 ||
1499                                 e->Iex.Binop.op == Iop_DivU32);
1500             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1501             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1502 #if (__mips_isa_rev >= 6)
1503             addInstr(env, MIPSInstr_Divr6(syned, div32, False,
1504                                           r_dst, r_srcL, r_srcR));
1505 #else
1506             addInstr(env, MIPSInstr_Div(syned, div32, r_srcL, r_srcR));
1507             addInstr(env, MIPSInstr_Mflo(r_dst));
1508 #endif
1509             return r_dst;
1510          }
1511 
1512          if (e->Iex.Binop.op == Iop_8HLto16
1513              || e->Iex.Binop.op == Iop_16HLto32) {
1514             HReg tHi   = iselWordExpr_R(env, e->Iex.Binop.arg1);
1515             HReg tLo   = iselWordExpr_R(env, e->Iex.Binop.arg2);
1516             HReg tLo_1 = newVRegI(env);
1517             HReg tHi_1 = newVRegI(env);
1518             HReg r_dst = newVRegI(env);
1519             UInt shift = 0;
1520             UInt mask  = 0;
1521             switch (e->Iex.Binop.op) {
1522                case Iop_8HLto16:
1523                   shift = 8;
1524                   mask  = 0xff;
1525                   break;
1526                case Iop_16HLto32:
1527                   shift = 16;
1528                   mask  = 0xffff;
1529                   break;
1530                default:
1531                   break;
1532             }
1533 
1534             /* sll tHi_1, tHi,   shift
1535                and tLo_1, tLo,   mask
1536                or  r_dst, tHi_1, tLo_1 */
1537             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tHi_1, tHi,
1538                                          MIPSRH_Imm(False, shift)));
1539             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1540                           MIPSRH_Imm(False, mask)));
1541             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1542                           MIPSRH_Reg(tLo_1)));
1543             return r_dst;
1544          }
1545 
1546          if (e->Iex.Binop.op == Iop_32HLto64) {
1547             vassert(mode64);
1548             HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
1549             HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
1550             HReg tLo_1 = newVRegI(env);
1551             HReg tHi_1 = newVRegI(env);
1552             HReg r_dst = newVRegI(env);
1553             HReg mask = newVRegI(env);
1554 
1555             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
1556                                          MIPSRH_Imm(False, 32)));
1557 
1558             addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1559             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1560                           MIPSRH_Reg(mask)));
1561             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1562                           MIPSRH_Reg(tLo_1)));
1563 
1564             return r_dst;
1565          }
1566 
1567          if (e->Iex.Binop.op == Iop_F32toI64S) {
1568             vassert(mode64);
1569             HReg valS = newVRegI(env);
1570             HReg tmpF = newVRegF(env);
1571             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
1572 
1573             /* CVTLS tmpF, valF */
1574             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1575             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpF, valF));
1576             set_MIPS_rounding_default(env);
1577 
1578             /* Doubleword Move from Floating Point
1579                dmfc1 valS, tmpF */
1580             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
1581 
1582             return valS;
1583          }
1584 
1585          if (e->Iex.Binop.op == Iop_F64toI64S) {
1586             vassert(mode64);
1587             HReg valS = newVRegI(env);
1588             HReg tmpF = newVRegF(env);
1589             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
1590 
1591             /* CVTLS tmpF, valF */
1592             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1593             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, tmpF, valF));
1594             set_MIPS_rounding_default(env);
1595 
1596             /* Doubleword Move from Floating Point
1597                dmfc1 valS, tmpF */
1598             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
1599 
1600             return valS;
1601          }
1602 
1603          if (e->Iex.Binop.op == Iop_F64toI32S) {
1604             HReg valD;
1605             if (mode64)
1606                valD = iselFltExpr(env, e->Iex.Binop.arg2);
1607             else
1608                valD = iselDblExpr(env, e->Iex.Binop.arg2);
1609             HReg valS = newVRegF(env);
1610             HReg r_dst = newVRegI(env);
1611 
1612             /* CVTWD valS, valD */
1613             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1614             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
1615             set_MIPS_rounding_default(env);
1616 
1617             /* Move Word From Floating Point
1618                mfc1 r_dst, valS */
1619             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1620 
1621             return r_dst;
1622          }
1623 
1624          if (e->Iex.Binop.op == Iop_F32toI32U) {
1625             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
1626             HReg tmpD = newVRegD(env);
1627             HReg r_dst  = newVRegI(env);
1628             MIPSAMode *am_addr;
1629 
1630             /* CVTLS tmpD, valF */
1631             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1632             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
1633             set_MIPS_rounding_default(env);
1634 
1635             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
1636             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
1637 
1638             /* store as F64 */
1639             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
1640                                            am_addr));
1641             /* load as 2xI32 */
1642 #if defined (_MIPSEL)
1643             addInstr(env, MIPSInstr_Load(4, r_dst, am_addr, mode64));
1644 #elif defined (_MIPSEB)
1645             addInstr(env, MIPSInstr_Load(4, r_dst, nextMIPSAModeFloat(am_addr),
1646                                          mode64));
1647 #endif
1648 
1649             /* Reset SP */
1650             add_to_sp(env, 16);
1651 
1652             return r_dst;
1653          }
1654 
1655          if (e->Iex.Binop.op == Iop_F64toI64U) {
1656             HReg r_src;
1657             HReg tmp = newVRegV(env);
1658             vassert(has_msa);
1659             r_src = iselFltExpr( env, e->Iex.Binop.arg2);
1660             set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
1661             addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_U, MSA_F_DW, tmp, r_src));
1662             HReg r_dst = newVRegI(env);
1663             addInstr(env,
1664                      MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_dst, MSA_DFN_D | 0));
1665             set_MIPS_rounding_default_MSA(env);
1666             return r_dst;
1667          }
1668 
1669          if (e->Iex.Binop.op == Iop_GetElem8x16) {
1670             HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
1671             HReg r_dst = newVRegI(env);
1672             MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
1673             vassert(has_msa);
1674             switch (tmp->tag) {
1675                case Mrh_Imm:
1676                   addInstr(env,
1677                            MIPSInstr_MsaElm(MSA_COPY_U, v_src, r_dst,
1678                                             MSA_DFN_B |
1679                                             (tmp->Mrh.Imm.imm16 & 0x0f)));
1680                   break;
1681 
1682                case Mrh_Reg: {
1683                      HReg v_tmp = newVRegV(env);
1684                      addInstr(env,
1685                               MIPSInstr_Msa3R(MSA_SPLAT, MSA_B, v_tmp, v_src,
1686                                               tmp->Mrh.Reg.reg));
1687                      addInstr(env,
1688                               MIPSInstr_MsaElm(MSA_COPY_U, v_tmp, r_dst,
1689                                                MSA_DFN_B));
1690                      break;
1691                   }
1692             }
1693 
1694             return r_dst;
1695          }
1696 
1697 
1698          if (e->Iex.Binop.op == Iop_GetElem16x8) {
1699             HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
1700             HReg r_dst = newVRegI(env);
1701             MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
1702             vassert(has_msa);
1703             switch (tmp->tag) {
1704                case Mrh_Imm:
1705                   addInstr(env,
1706                            MIPSInstr_MsaElm(MSA_COPY_U, v_src, r_dst,
1707                                             MSA_DFN_H |
1708                                             (tmp->Mrh.Imm.imm16 & 0x07)));
1709                   break;
1710 
1711                case Mrh_Reg: {
1712                      HReg v_tmp = newVRegV(env);
1713                      addInstr(env,
1714                               MIPSInstr_Msa3R(MSA_SPLAT, MSA_H, v_tmp, v_src,
1715                                               tmp->Mrh.Reg.reg));
1716                      addInstr(env,
1717                               MIPSInstr_MsaElm(MSA_COPY_U, v_tmp, r_dst,
1718                                                MSA_DFN_H));
1719                      break;
1720                   }
1721             }
1722 
1723             return r_dst;
1724          }
1725 
1726          if (e->Iex.Binop.op == Iop_GetElem32x4) {
1727             HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
1728             HReg r_dst = newVRegI(env);
1729             MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
1730             vassert(has_msa);
1731             switch (tmp->tag) {
1732                case Mrh_Imm:
1733                   addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dst,
1734                                                  MSA_DFN_W |
1735                                                  (tmp->Mrh.Imm.imm16 & 0x03)));
1736                   break;
1737 
1738                case Mrh_Reg: {
1739                      HReg v_tmp = newVRegV(env);
1740                      addInstr(env,
1741                               MIPSInstr_Msa3R(MSA_SPLAT, MSA_W, v_tmp, v_src,
1742                                               tmp->Mrh.Reg.reg));
1743                      addInstr(env,
1744                               MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dst,
1745                                                MSA_DFN_W));
1746                      break;
1747                   }
1748             }
1749 
1750             return r_dst;
1751          }
1752          if (e->Iex.Binop.op == Iop_GetElem64x2) {
1753             vassert(mode64);
1754             HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
1755             HReg r_dst = newVRegI(env);
1756             MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
1757             vassert(has_msa);
1758             switch (tmp->tag) {
1759                case Mrh_Imm:
1760                   addInstr(env,
1761                            MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dst,
1762                                             MSA_DFN_D |
1763                                             (tmp->Mrh.Imm.imm16 & 0x01)));
1764                   break;
1765 
1766                case Mrh_Reg: {
1767                      HReg v_tmp = newVRegV(env);
1768                      addInstr(env,
1769                               MIPSInstr_Msa3R(MSA_SPLAT, MSA_D, v_tmp, v_src,
1770                                               tmp->Mrh.Reg.reg));
1771                      addInstr(env,
1772                               MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dst,
1773                                                MSA_DFN_D));
1774                      break;
1775                   }
1776             }
1777 
1778             return r_dst;
1779          }
1780 
1781          if (e->Iex.Binop.op == Iop_F32toI32S) {
1782             HReg valS = newVRegF(env);
1783             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
1784             HReg r_dst = newVRegI(env);
1785 
1786             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1787             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
1788             set_MIPS_rounding_default(env);
1789 
1790             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1791 
1792             return r_dst;
1793          }
1794 
1795          /* -------- DSP ASE -------- */
1796          /* All used cases involving host-side helper calls. */
1797          void* fn = NULL;
1798          switch (e->Iex.Binop.op) {
1799             case Iop_HAdd8Ux4:
1800                fn = &h_generic_calc_HAdd8Ux4; break;
1801             case Iop_HSub8Ux4:
1802                fn = &h_generic_calc_HSub8Ux4; break;
1803             case Iop_HSub16Sx2:
1804                fn = &h_generic_calc_HSub16Sx2; break;
1805             case Iop_QSub8Ux4:
1806                fn = &h_generic_calc_QSub8Ux4; break;
1807             default:
1808                   break;
1809          }
1810 
1811          /* What's the retloc? */
1812          RetLoc rloc = mk_RetLoc_INVALID();
1813          if (ty == Ity_I32) {
1814             rloc = mk_RetLoc_simple(RLPri_Int);
1815          }
1816          else if (ty == Ity_I64) {
1817             rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
1818                             mk_RetLoc_simple(RLPri_2Int);
1819          }
1820          else {
1821             goto irreducible;
1822          }
1823 
1824          if (fn) {
1825             HReg regL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1826             HReg regR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1827             HReg res  = newVRegI(env);
1828             addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
1829             addInstr(env, mk_iMOVds_RR(hregMIPS_GPR5(env->mode64), regR));
1830             argiregs |= (1 << 4);
1831             argiregs |= (1 << 5);
1832             addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
1833                                                 (Addr)fn,
1834                                                 argiregs, rloc));
1835             addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
1836             return res;
1837          }
1838       break;
1839    }
1840 
1841    /* --------- UNARY OP --------- */
1842    case Iex_Unop: {
1843       IROp op_unop = e->Iex.Unop.op;
1844 
1845       switch (op_unop) {
1846          case Iop_1Sto8:
1847          case Iop_1Sto16:
1848          case Iop_1Sto32:
1849          case Iop_8Sto16:
1850          case Iop_8Sto32:
1851          case Iop_16Sto32:
1852          case Iop_16Sto64:
1853          case Iop_8Sto64:
1854          case Iop_1Sto64: {
1855             HReg r_dst = newVRegI(env);
1856             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1857             Bool sz32;
1858             UShort amt;
1859             switch (op_unop) {
1860                case Iop_1Sto8:
1861                   amt = 31;
1862                   sz32 = True;
1863                   break;
1864                case Iop_1Sto16:
1865                   amt = 31;
1866                   sz32 = True;
1867                   break;
1868                case Iop_1Sto32:
1869                   amt = 31;
1870                   sz32 = True;
1871                   break;
1872                case Iop_16Sto32:
1873                   amt = 16;
1874                   sz32 = True;
1875                   break;
1876                case Iop_16Sto64:
1877                   amt = 48;
1878                   sz32 = False;
1879                   break;
1880                case Iop_8Sto16:
1881                   amt = 24;
1882                   sz32 = True;
1883                   break;
1884                case Iop_8Sto32:
1885                   amt = 24;
1886                   sz32 = True;
1887                   break;
1888                case Iop_8Sto64:
1889                   amt = 56;
1890                   sz32 = False;
1891                   break;
1892                case Iop_1Sto64:
1893                   amt = 63;
1894                   sz32 = False;
1895                   break;
1896                default:
1897                   vassert(0);
1898             }
1899 
1900             addInstr(env, MIPSInstr_Shft(Mshft_SLL, sz32, r_dst, r_src,
1901                                          MIPSRH_Imm(False, amt)));
1902             addInstr(env, MIPSInstr_Shft(Mshft_SRA, sz32, r_dst, r_dst,
1903                                          MIPSRH_Imm(False, amt)));
1904             return r_dst;
1905          }
1906 
1907          /* not(x) = nor(x,x) */
1908          case Iop_Not1: {
1909             HReg r_dst = newVRegI(env);
1910             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
1911             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
1912 
1913             addInstr(env, MIPSInstr_LI(r_dst, 0x1));
1914             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
1915             return r_dst;
1916          }
1917 
1918          case Iop_Not8:
1919          case Iop_Not16:
1920          case Iop_Not32:
1921          case Iop_Not64: {
1922             HReg r_dst = newVRegI(env);
1923             HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
1924             MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
1925 
1926             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
1927             return r_dst;
1928          }
1929 
1930          case Iop_ReinterpF32asI32: {
1931             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1932             HReg r_dst = newVRegI(env);
1933 
1934             /* Move Word From Floating Point
1935                mfc1 r_dst, fr_src */
1936             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, fr_src));
1937 
1938             return r_dst;
1939          }
1940 
1941          case Iop_ReinterpF64asI64: {
1942             vassert(mode64);
1943             HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1944             HReg r_dst = newVRegI(env);
1945 
1946             /* Doubleword Move from Floating Point
1947                mfc1 r_dst, fr_src */
1948             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, r_dst, fr_src));
1949 
1950             return r_dst;
1951          }
1952 
1953          case Iop_F64toI32S: {
1954             HReg valD;
1955             if (mode64)
1956                valD = iselFltExpr(env, e->Iex.Binop.arg2);
1957             else
1958                valD = iselDblExpr(env, e->Iex.Binop.arg2);
1959             HReg valS = newVRegF(env);
1960             HReg r_dst = newVRegI(env);
1961 
1962             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1963             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
1964             set_MIPS_rounding_default(env);
1965 
1966             /* Move Word From Floating Point
1967                mfc1 r_dst, valS */
1968             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1969 
1970             return r_dst;
1971          }
1972 
1973          case Iop_16to8:
1974          case Iop_32to1:
1975          case Iop_32to8:
1976          case Iop_32to16:
1977             return iselWordExpr_R(env, e->Iex.Unop.arg);
1978 
1979          case Iop_32HIto16: {
1980             HReg r_dst = newVRegI(env);
1981             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1982             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
1983                                          r_dst, r_src, MIPSRH_Imm(False, 16)));
1984             return r_dst;
1985          }
1986 
1987          case Iop_64to1:
1988          case Iop_64to8: {
1989             HReg r_src, r_dst;
1990             UShort mask = (op_unop == Iop_64to1) ? 0x1 : 0xFF;
1991             r_dst = newVRegI(env);
1992             if (mode64)
1993                r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1994             else {
1995               HReg tmp;
1996               iselInt64Expr(&tmp, &r_src, env, e->Iex.Unop.arg);
1997             }
1998             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
1999                           MIPSRH_Imm(False, mask)));
2000             return r_dst;
2001          }
2002 
2003          case Iop_16HIto8: {
2004             HReg r_dst = newVRegI(env);
2005             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2006             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2007                                          r_dst, r_src, MIPSRH_Imm(False, 8)));
2008             return r_dst;
2009          }
2010 
2011          case Iop_1Uto8:
2012          case Iop_1Uto32:
2013          case Iop_1Uto64:
2014          case Iop_8Uto16:
2015          case Iop_8Uto32:
2016          case Iop_8Uto64:
2017          case Iop_16Uto32:
2018          case Iop_16Uto64: {
2019             HReg r_dst = newVRegI(env);
2020             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2021             UShort mask = 0;
2022             switch (op_unop) {
2023                case Iop_1Uto64:
2024                   vassert(mode64);
2025                case Iop_1Uto8:
2026                case Iop_1Uto32:
2027                   mask = toUShort(0x1);
2028                   break;
2029                case Iop_8Uto64:
2030                   vassert(mode64);
2031                case Iop_8Uto16:
2032                case Iop_8Uto32:
2033                   mask = toUShort(0xFF);
2034                   break;
2035                case Iop_16Uto64:
2036                   vassert(mode64);
2037                case Iop_16Uto32:
2038                   mask = toUShort(0xFFFF);
2039                   break;
2040                default:
2041                   vassert(0);
2042                   break;
2043             }
2044             addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
2045                           MIPSRH_Imm(False, mask)));
2046             return r_dst;
2047          }
2048 
2049          case Iop_32Uto64: {
2050             HReg r_dst = newVRegI(env);
2051             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2052             vassert(mode64);
2053             addInstr(env, MIPSInstr_Shft(Mshft_SLL, False /*!32bit shift */,
2054                                          r_dst, r_src, MIPSRH_Imm(False, 32)));
2055             addInstr(env, MIPSInstr_Shft(Mshft_SRL, False /*!32bit shift */,
2056                                          r_dst, r_dst, MIPSRH_Imm(False, 32)));
2057             return r_dst;
2058          }
2059 
2060          case Iop_64HIto32: {
2061             if (env->mode64) {
2062                HReg r_dst = newVRegI(env);
2063                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2064                addInstr(env, MIPSInstr_Shft(Mshft_SRA, False /*64bit shift */,
2065                        r_dst, r_src, MIPSRH_Imm(True, 32)));
2066                return r_dst;
2067             } else {
2068                HReg rHi, rLo;
2069                iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2070                return rHi;
2071             }
2072          }
2073 
2074          case Iop_64to32: {
2075             if (env->mode64) {
2076                HReg r_dst = newVRegI(env);
2077                r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
2078                return r_dst;
2079             } else {
2080                HReg rHi, rLo;
2081                iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2082                return rLo;
2083             }
2084          }
2085 
2086          case Iop_64to16: {
2087             vassert(env->mode64);
2088             HReg r_dst = newVRegI(env);
2089             r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
2090             return r_dst;
2091          }
2092 
2093          case Iop_32Sto64: {
2094             HReg r_dst = newVRegI(env);
2095             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2096             vassert(mode64);
2097             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*!32bit shift */,
2098                                          r_dst, r_src, MIPSRH_Imm(True, 0)));
2099             return r_dst;
2100          }
2101 
2102          case Iop_CmpNEZ8:
2103          case Iop_CmpNEZ16: {
2104             HReg r_dst = newVRegI(env);
2105             HReg tmp = newVRegI(env);
2106             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2107             UShort mask = (op_unop == Iop_CmpNEZ8) ? 0xFF : 0xFFFF;
2108 
2109             addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
2110                                         MIPSRH_Imm(False, mask)));
2111             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
2112                                         hregMIPS_GPR0(mode64), MIPScc_NE));
2113             return r_dst;
2114          }
2115 
2116          case Iop_CmpNEZ32: {
2117             HReg r_dst = newVRegI(env);
2118             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2119 
2120             addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
2121                                         hregMIPS_GPR0(mode64), MIPScc_NE));
2122             return r_dst;
2123          }
2124 
2125          case Iop_CmpwNEZ32: {
2126             HReg r_dst = newVRegI(env);
2127             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2128 
2129             addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
2130                           MIPSRH_Reg(r_src)));
2131 
2132             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2133                                         MIPSRH_Reg(r_src)));
2134             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
2135                                          MIPSRH_Imm(False, 31)));
2136             return r_dst;
2137          }
2138 
2139          case Iop_Left8:
2140          case Iop_Left16:
2141          case Iop_Left32:
2142          case Iop_Left64: {
2143             if (op_unop == Iop_Left64 && !mode64)
2144                goto irreducible;
2145             HReg r_dst = newVRegI(env);
2146             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2147             MIPSAluOp op = (op_unop == Iop_Left64) ? Malu_DSUB : Malu_SUB;
2148             addInstr(env, MIPSInstr_Alu(op, r_dst,
2149                                         hregMIPS_GPR0(mode64),
2150                                         MIPSRH_Reg(r_src)));
2151             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2152                           MIPSRH_Reg(r_src)));
2153             return r_dst;
2154          }
2155 
2156          case Iop_Clz64:
2157             vassert(mode64);
2158          case Iop_Clz32: {
2159             HReg r_dst = newVRegI(env);
2160             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2161             MIPSUnaryOp op = (op_unop == Iop_Clz64) ? Mun_DCLZ : Mun_CLZ;
2162             addInstr(env, MIPSInstr_Unary(op, r_dst, r_src));
2163             return r_dst;
2164          }
2165 
2166          case Iop_CmpNEZ64: {
2167             HReg hi, lo;
2168             HReg r_dst = newVRegI(env);
2169             HReg r_src;
2170             if (env->mode64) {
2171                r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2172             } else {
2173                r_src = newVRegI(env);
2174                iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
2175                addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
2176             }
2177             addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
2178                                         hregMIPS_GPR0(mode64), MIPScc_NE));
2179             return r_dst;
2180          }
2181 
2182          case Iop_CmpwNEZ64: {
2183             HReg tmp1;
2184             HReg tmp2 = newVRegI(env);
2185             vassert(env->mode64);
2186             tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
2187 
2188             addInstr(env, MIPSInstr_Alu(Malu_DSUB, tmp2, hregMIPS_GPR0(mode64),
2189                           MIPSRH_Reg(tmp1)));
2190 
2191             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
2192             addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
2193                                          MIPSRH_Imm (False, 63)));
2194             return tmp2;
2195          }
2196 
2197          case Iop_128HIto64: {
2198             vassert(mode64);
2199             HReg rHi, rLo;
2200             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2201             return rHi;  /* and abandon rLo .. poor wee thing :-) */
2202          }
2203 
2204          case Iop_128to64: {
2205             vassert(mode64);
2206             HReg rHi, rLo;
2207             iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2208             return rLo;  /* and abandon rLo .. poor wee thing :-) */
2209          }
2210 
2211          case Iop_V128to32: {
2212             HReg i_dst = newVRegI(env);
2213             HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2214             vassert(has_msa);
2215             addInstr(env,
2216                      MIPSInstr_MsaElm(MSA_COPY_S, v_src, i_dst, MSA_DFN_W));
2217             return i_dst;
2218          }
2219 
2220          case Iop_V128HIto64: {
2221             vassert(mode64);
2222             vassert(has_msa);
2223             HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2224             HReg reg = newVRegI(env);
2225             addInstr(env,
2226                      MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 1));
2227             return reg;
2228          }
2229 
2230          case Iop_V128to64: {
2231             vassert(mode64);
2232             vassert(has_msa);
2233             HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2234             HReg reg = newVRegI(env);
2235             addInstr(env,
2236                      MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 0));
2237             return reg;
2238          }
2239 
2240          case Iop_F32toF16x4: {
2241             vassert(mode64);
2242             vassert(has_msa);
2243             HReg v_arg = iselV128Expr(env, e->Iex.Unop.arg);
2244             HReg v_src = newVRegV(env);
2245             set_guest_MIPS_rounding_mode_MSA(env);
2246             addInstr(env,
2247                      MIPSInstr_Msa3RF(MSA_FEXDO, MSA_F_WH,
2248                                       v_src, v_arg, v_arg));
2249             set_MIPS_rounding_default_MSA(env);
2250             HReg reg = newVRegI(env);
2251             addInstr(env,
2252                      MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 0));
2253             return reg;
2254          }
2255 
2256 
2257          default:
2258             break;
2259       }
2260 
2261       /* -------- DSP ASE -------- */
2262       /* All Unop cases involving host-side helper calls. */
2263       void* fn = NULL;
2264       switch (e->Iex.Unop.op) {
2265          case Iop_CmpNEZ16x2:
2266             fn = &h_generic_calc_CmpNEZ16x2; break;
2267          case Iop_CmpNEZ8x4:
2268             fn = &h_generic_calc_CmpNEZ8x4; break;
2269          default:
2270             break;
2271       }
2272 
2273       RetLoc rloc = mk_RetLoc_INVALID();
2274       if (ty == Ity_I32) {
2275          rloc = mk_RetLoc_simple(RLPri_Int);
2276       }
2277       else if (ty == Ity_I64) {
2278          rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
2279                          mk_RetLoc_simple(RLPri_2Int);
2280       }
2281       else {
2282          goto irreducible;
2283       }
2284 
2285       if (fn) {
2286          HReg regL = iselWordExpr_R(env, e->Iex.Unop.arg);
2287          HReg res  = newVRegI(env);
2288          addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
2289          argiregs |= (1 << 4);
2290          addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
2291                                              (Addr)fn,
2292                                              argiregs, rloc));
2293          addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
2294          return res;
2295       }
2296 
2297       break;
2298    }
2299 
2300    /* --------- GET --------- */
2301    case Iex_Get: {
2302       if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
2303           || ((ty == Ity_I64) && mode64)) {
2304          HReg r_dst = newVRegI(env);
2305 
2306          MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
2307                                            GuestStatePointer(mode64));
2308          addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
2309                                       mode64));
2310          return r_dst;
2311       }
2312       break;
2313    }
2314 
2315    /* --------- ITE --------- */
2316    case Iex_ITE: {
2317       if ((ty == Ity_I8 || ty == Ity_I16 ||
2318            ty == Ity_I32 || ((ty == Ity_I64))) &&
2319            typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
2320          HReg r0     = iselWordExpr_R(env, e->Iex.ITE.iffalse);
2321          HReg r1     = iselWordExpr_R(env, e->Iex.ITE.iftrue);
2322          HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
2323          HReg r_dst = newVRegI(env);
2324          /*
2325           * r_dst = r0
2326           * movn r_dst, r1, r_cond
2327           */
2328 #if (__mips_isa_rev >= 6)
2329          HReg r_temp  = newVRegI(env);
2330          addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dst, r0, r_cond));
2331          addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, r1, r_cond));
2332          addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2333                           MIPSRH_Reg(r_temp)));
2334 
2335 #else
2336          addInstr(env, mk_iMOVds_RR(r_dst, r0));
2337          addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, r1, r_cond));
2338 #endif
2339          return r_dst;
2340       }
2341       break;
2342    }
2343 
2344    /* --------- LITERAL --------- */
2345    /* 32/16/8-bit literals */
2346    case Iex_Const: {
2347       Long l;
2348       HReg r_dst = newVRegI(env);
2349       IRConst *con = e->Iex.Const.con;
2350       switch (con->tag) {
2351          case Ico_U64:
2352             if (!mode64)
2353                goto irreducible;
2354             l = (Long) con->Ico.U64;
2355             break;
2356          case Ico_U32:
2357             l = (Long) (Int) con->Ico.U32;
2358             break;
2359          case Ico_U16:
2360             l = (Long) (Int) (Short) con->Ico.U16;
2361             break;
2362          case Ico_U8:
2363             l = (Long) (Int) (Char) con->Ico.U8;
2364             break;
2365          default:
2366             vpanic("iselIntExpr_R.const(mips)");
2367       }
2368       addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
2369       return r_dst;
2370    }
2371 
2372    /* --------- CCALL --------- */
2373    case Iex_CCall: {
2374       HReg r_dst = newVRegI(env);
2375       vassert(ty == e->Iex.CCall.retty);
2376 
2377       /* be very restrictive for now.  Only 32/64-bit ints allowed for
2378          args, and 64 and 32 bits for return type.  Don't forget to change
2379          the RetLoc if more return types are allowed in future. */
2380       if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32)
2381          goto irreducible;
2382 
2383       /* Marshal args, do the call, clear stack. */
2384       UInt   addToSp = 0;
2385       RetLoc rloc    = mk_RetLoc_INVALID();
2386       doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
2387                    e->Iex.CCall.retty, e->Iex.CCall.args );
2388 
2389       vassert(is_sane_RetLoc(rloc));
2390       vassert(rloc.pri == RLPri_Int);
2391       vassert(addToSp == 0);
2392       addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
2393       return r_dst;
2394    }
2395 
2396 #if (__mips_isa_rev >= 6)
2397    case Iex_Qop: {
2398       HReg dst = newVRegI(env);
2399       HReg src1 = iselWordExpr_R(env, e->Iex.Qop.details->arg1);
2400       HReg src2 = iselWordExpr_R(env, e->Iex.Qop.details->arg2);
2401       HReg src3 = iselWordExpr_R(env, e->Iex.Qop.details->arg3);
2402       HReg src4 = iselWordExpr_R(env, e->Iex.Qop.details->arg4);
2403       switch (e->Iex.Qop.details->op) {
2404         case Iop_Rotx32:
2405           addInstr(env, MIPSInstr_Bitswap(Rotx32, dst, src1, src2, src3, src4));
2406           break;
2407         case Iop_Rotx64:
2408           addInstr(env, MIPSInstr_Bitswap(Rotx64, dst, src1, src2, src3, src4));
2409           break;
2410         default:
2411           break;
2412       }
2413       return dst;
2414    }
2415 #endif
2416 
2417    default:
2418       break;
2419    }  /* end switch(e->tag) */
2420 
2421    /* We get here if no pattern matched. */
2422    irreducible:
2423       vex_printf("--------------->\n");
2424       if (e->tag == Iex_RdTmp)
2425          vex_printf("Iex_RdTmp \n");
2426       ppIRExpr(e);
2427 
2428       vpanic("iselWordExpr_R(mips): cannot reduce tree");
2429 }
2430 
2431 /* --------------------- RH --------------------- */
2432 
2433 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2434    (reg-or-halfword-immediate).  It's important to specify whether the
2435    immediate is to be regarded as signed or not.  If yes, this will
2436    never return -32768 as an immediate; this guaranteed that all
2437    signed immediates that are return can have their sign inverted if
2438    need be. */
2439 
iselWordExpr_RH(ISelEnv * env,Bool syned,IRExpr * e)2440 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
2441 {
2442    MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
2443    /* sanity checks ... */
2444    switch (ri->tag) {
2445       case Mrh_Imm:
2446          vassert(ri->Mrh.Imm.syned == syned);
2447          if (syned)
2448             vassert(ri->Mrh.Imm.imm16 != 0x8000);
2449          return ri;
2450       case Mrh_Reg:
2451          vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2452          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2453          return ri;
2454       default:
2455          vpanic("iselIntExpr_RH: unknown mips RH tag");
2456    }
2457 }
2458 
2459 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,IRExpr * e)2460 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
2461 {
2462    ULong u;
2463    Long l;
2464    IRType ty = typeOfIRExpr(env->type_env, e);
2465    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
2466           ((ty == Ity_I64) && env->mode64));
2467 
2468    /* special case: immediate */
2469    if (e->tag == Iex_Const) {
2470       IRConst *con = e->Iex.Const.con;
2471       /* What value are we aiming to generate? */
2472       switch (con->tag) {
2473          /* Note: Not sign-extending - we carry 'syned' around */
2474          case Ico_U64:
2475             vassert(env->mode64);
2476             u = con->Ico.U64;
2477             break;
2478          case Ico_U32:
2479             u = 0xFFFFFFFF & con->Ico.U32;
2480             break;
2481          case Ico_U16:
2482             u = 0x0000FFFF & con->Ico.U16;
2483             break;
2484          case Ico_U8:
2485             u = 0x000000FF & con->Ico.U8;
2486             break;
2487          default:
2488             vpanic("iselIntExpr_RH.Iex_Const(mips)");
2489       }
2490       l = (Long) u;
2491       /* Now figure out if it's representable. */
2492       if (!syned && u <= 65535) {
2493          return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
2494       }
2495       if (syned && l >= -32767 && l <= 32767) {
2496          return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
2497       }
2498       /* no luck; use the Slow Way. */
2499    }
2500    /* default case: calculate into a register and return that */
2501    return MIPSRH_Reg(iselWordExpr_R(env, e));
2502 }
2503 
2504 /* --------------------- RH5u --------------------- */
2505 
2506 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2507    being an immediate in the range 1 .. 31 inclusive.  Used for doing
2508    shift amounts. */
2509 
iselWordExpr_RH5u(ISelEnv * env,IRExpr * e)2510 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
2511 {
2512    MIPSRH *ri;
2513    ri = iselWordExpr_RH5u_wrk(env, e);
2514    /* sanity checks ... */
2515    switch (ri->tag) {
2516       case Mrh_Imm:
2517          vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
2518          vassert(!ri->Mrh.Imm.syned);
2519          return ri;
2520       case Mrh_Reg:
2521          vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
2522          vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2523          return ri;
2524       default:
2525          vpanic("iselIntExpr_RH5u: unknown mips RH tag");
2526    }
2527 }
2528 
2529 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH5u_wrk(ISelEnv * env,IRExpr * e)2530 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
2531 {
2532    IRType ty = typeOfIRExpr(env->type_env, e);
2533    vassert(ty == Ity_I8);
2534 
2535    /* special case: immediate */
2536    if (e->tag == Iex_Const
2537        && e->Iex.Const.con->tag == Ico_U8
2538        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
2539       return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
2540    }
2541 
2542    /* default case: calculate into a register and return that */
2543    return MIPSRH_Reg(iselWordExpr_R(env, e));
2544 }
2545 
2546 /* --------------------- RH6u --------------------- */
2547 
iselWordExpr_RH6u(ISelEnv * env,IRExpr * e)2548 static MIPSRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
2549 {
2550    MIPSRH *ri;
2551    ri = iselWordExpr_RH6u_wrk(env, e);
2552    /* sanity checks ... */
2553    switch (ri->tag) {
2554    case Mrh_Imm:
2555       vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 63);
2556       vassert(!ri->Mrh.Imm.syned);
2557       return ri;
2558    case Mrh_Reg:
2559       vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2560       vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2561       return ri;
2562    default:
2563       vpanic("iselIntExpr_RH6u: unknown RI tag");
2564    }
2565 }
2566 
2567 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,IRExpr * e)2568 static MIPSRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
2569 {
2570    IRType ty = typeOfIRExpr(env->type_env, e);
2571    vassert(ty == Ity_I8);
2572 
2573    /* special case: immediate */
2574    if (e->tag == Iex_Const
2575        && e->Iex.Const.con->tag == Ico_U8
2576        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
2577    {
2578       return MIPSRH_Imm(False /*unsigned */ ,
2579               e->Iex.Const.con->Ico.U8);
2580    }
2581 
2582    /* default case: calculate into a register and return that */
2583    return MIPSRH_Reg(iselWordExpr_R(env, e));
2584 }
2585 /* --------------------- RH7u --------------------- */
2586 
iselWordExpr_RH7u(ISelEnv * env,IRExpr * e)2587 static MIPSRH *iselWordExpr_RH7u ( ISelEnv * env, IRExpr * e )
2588 {
2589    MIPSRH *ri;
2590    ri = iselWordExpr_RH7u_wrk(env, e);
2591    /* sanity checks ... */
2592    switch (ri->tag) {
2593    case Mrh_Imm:
2594       vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 127);
2595       vassert(!ri->Mrh.Imm.syned);
2596       return ri;
2597    case Mrh_Reg:
2598       vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2599       vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2600       return ri;
2601    default:
2602       vpanic("iselIntExpr_RH7u: unknown RI tag");
2603    }
2604 }
2605 
2606 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH7u_wrk(ISelEnv * env,IRExpr * e)2607 static MIPSRH *iselWordExpr_RH7u_wrk ( ISelEnv * env, IRExpr * e )
2608 {
2609    IRType ty = typeOfIRExpr(env->type_env, e);
2610    vassert(ty == Ity_I8);
2611 
2612    /* special case: immediate */
2613    if (e->tag == Iex_Const
2614        && e->Iex.Const.con->tag == Ico_U8
2615        && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 127)
2616    {
2617       return MIPSRH_Imm(False /*unsigned */ ,
2618               e->Iex.Const.con->Ico.U8);
2619    }
2620 
2621    /* default case: calculate into a register and return that */
2622    return MIPSRH_Reg(iselWordExpr_R(env, e));
2623 }
2624 
2625 
2626 /* --------------------- CONDCODE --------------------- */
2627 
2628 /* Generate code to evaluated a bit-typed expression, returning the
2629    condition code which would correspond when the expression would
2630    notionally have returned 1. */
2631 
iselCondCode(ISelEnv * env,IRExpr * e)2632 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
2633 {
2634    MIPSCondCode cc = iselCondCode_wrk(env,e);
2635    vassert(cc != MIPScc_NV);
2636    return cc;
2637 }
2638 
2639 /* DO NOT CALL THIS DIRECTLY ! */
iselCondCode_wrk(ISelEnv * env,IRExpr * e)2640 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
2641 {
2642    vassert(e);
2643    vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
2644    /* Cmp*32*(x,y) ? */
2645    if (e->Iex.Binop.op == Iop_CmpEQ32
2646        || e->Iex.Binop.op == Iop_CmpNE32
2647        || e->Iex.Binop.op == Iop_CmpNE64
2648        || e->Iex.Binop.op == Iop_CmpLT32S
2649        || e->Iex.Binop.op == Iop_CmpLT32U
2650        || e->Iex.Binop.op == Iop_CmpLT64U
2651        || e->Iex.Binop.op == Iop_CmpLE32S
2652        || e->Iex.Binop.op == Iop_CmpLE64S
2653        || e->Iex.Binop.op == Iop_CmpLT64S
2654        || e->Iex.Binop.op == Iop_CmpEQ64
2655        || e->Iex.Binop.op == Iop_CasCmpEQ32
2656        || e->Iex.Binop.op == Iop_CasCmpEQ64) {
2657 
2658       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
2659                    || e->Iex.Binop.op == Iop_CmpLE32S
2660                    || e->Iex.Binop.op == Iop_CmpLT64S
2661                    || e->Iex.Binop.op == Iop_CmpLE64S);
2662       Bool size32;
2663       HReg dst = newVRegI(env);
2664       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2665       HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
2666 
2667       MIPSCondCode cc;
2668 
2669       switch (e->Iex.Binop.op) {
2670          case Iop_CmpEQ32:
2671          case Iop_CasCmpEQ32:
2672             cc = MIPScc_EQ;
2673             size32 = True;
2674             break;
2675          case Iop_CmpNE32:
2676             cc = MIPScc_NE;
2677             size32 = True;
2678             break;
2679          case Iop_CmpNE64:
2680             cc = MIPScc_NE;
2681             size32 = False;
2682             break;
2683          case Iop_CmpLT32S:
2684             cc = MIPScc_LT;
2685             size32 = True;
2686             break;
2687          case Iop_CmpLT32U:
2688             cc = MIPScc_LO;
2689             size32 = True;
2690             break;
2691          case Iop_CmpLT64U:
2692             cc = MIPScc_LO;
2693             size32 = False;
2694             break;
2695          case Iop_CmpLE32S:
2696             cc = MIPScc_LE;
2697             size32 = True;
2698             break;
2699          case Iop_CmpLE64S:
2700             cc = MIPScc_LE;
2701             size32 = False;
2702             break;
2703          case Iop_CmpLT64S:
2704             cc = MIPScc_LT;
2705             size32 = False;
2706             break;
2707          case Iop_CmpEQ64:
2708          case Iop_CasCmpEQ64:
2709             cc = MIPScc_EQ;
2710             size32 = False;
2711             break;
2712          default:
2713             vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
2714             break;
2715       }
2716 
2717       addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
2718       /* Store result to guest_COND */
2719       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2720 
2721       addInstr(env, MIPSInstr_Store(4,
2722                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2723                             am_addr->Mam.IR.base),
2724                dst, mode64));
2725       return cc;
2726    }
2727    if (e->Iex.Binop.op == Iop_Not1) {
2728       HReg r_dst = newVRegI(env);
2729       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
2730       MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
2731 
2732       addInstr(env, MIPSInstr_LI(r_dst, 0x1));
2733       addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
2734       /* Store result to guest_COND */
2735       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2736 
2737       addInstr(env, MIPSInstr_Store(4,
2738                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2739                             am_addr->Mam.IR.base),
2740                r_dst, mode64));
2741       return MIPScc_NE;
2742    }
2743    if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
2744       HReg r_dst = iselWordExpr_R_wrk(env, e);
2745       /* Store result to guest_COND */
2746       MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2747 
2748       addInstr(env, MIPSInstr_Store(4,
2749                MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2750                             am_addr->Mam.IR.base),
2751                r_dst, mode64));
2752       return MIPScc_EQ;
2753    }
2754 
2755    vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
2756    ppIRExpr(e);
2757    vpanic("iselCondCode(mips)");
2758 }
2759 
2760 /*---------------------------------------------------------*/
2761 /*--- ISEL: Vector expressions (128 bit - SIMD)         ---*/
2762 /*---------------------------------------------------------*/
2763 
2764 /* Compute a vector value into vector register.            */
iselV128Expr(ISelEnv * env,IRExpr * e)2765 static HReg iselV128Expr (ISelEnv* env, IRExpr* e) {
2766    vassert(has_msa);
2767    HReg r = iselV128Expr_wrk(env, e);
2768    vassert(hregClass(r) == HRcVec128);
2769    vassert(hregIsVirtual(r));
2770    return r;
2771 }
2772 
2773 /* DO NOT CALL THIS DIRECTLY ! */
iselV128Expr_wrk(ISelEnv * env,IRExpr * e)2774 static HReg iselV128Expr_wrk(ISelEnv* env, IRExpr* e) {
2775    IRType ty = typeOfIRExpr(env->type_env, e);
2776    vassert(e);
2777    vassert(ty == Ity_V128);
2778 
2779    if (e->tag == Iex_RdTmp) {
2780       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2781    }
2782 
2783    if (e->tag == Iex_Load) {
2784       vassert (e->Iex.Load.ty == Ity_V128);
2785       HReg v_dst = newVRegV(env);
2786       addInstr(env, MIPSInstr_MsaMi10(MSA_LD, 0, iselWordExpr_R(env,
2787                                       e->Iex.Load.addr), v_dst, MSA_B));
2788       return v_dst;
2789    }
2790 
2791    if (e->tag == Iex_Get) {
2792       HReg v_dst = newVRegV(env);
2793 #if defined(_MIPSEB)
2794       HReg r_addr = newVRegI(env);
2795       addInstr(env, MIPSInstr_Alu(mode64 ? Malu_DADD : Malu_ADD, r_addr, GuestStatePointer(mode64),
2796                                   MIPSRH_Imm(False, e->Iex.Get.offset)));
2797       addInstr(env, MIPSInstr_MsaMi10(MSA_LD, 0, r_addr, v_dst, MSA_B));
2798 #else
2799       vassert(!(e->Iex.Get.offset & 7));
2800       addInstr(env, MIPSInstr_MsaMi10(MSA_LD, e->Iex.Get.offset >> 3,
2801                                       GuestStatePointer(mode64), v_dst, MSA_D));
2802 #endif
2803       return v_dst;
2804    }
2805 
2806    if (e->tag == Iex_Unop) {
2807       IROp op_unop = e->Iex.Unop.op;
2808 
2809       switch (op_unop) {
2810          case Iop_Abs64x2: {
2811                HReg v_dst = newVRegV(env);
2812                HReg v_help = newVRegV(env);
2813                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2814                addInstr(env,
2815                         MIPSInstr_Msa3R(MSA_SUBV, MSA_D, v_help, v_src, v_src));
2816                addInstr(env,
2817                         MIPSInstr_Msa3R(MSA_ADD_A, MSA_D,
2818                                         v_dst, v_src, v_help));
2819                return v_dst;
2820             }
2821 
2822          case Iop_Abs32x4: {
2823                HReg v_dst = newVRegV(env);
2824                HReg v_help = newVRegV(env);
2825                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2826                addInstr(env,
2827                         MIPSInstr_Msa3R(MSA_SUBV, MSA_W, v_help, v_src, v_src));
2828                addInstr(env,
2829                         MIPSInstr_Msa3R(MSA_ADD_A, MSA_W,
2830                                         v_dst, v_src, v_help));
2831                return v_dst;
2832             }
2833 
2834          case Iop_Abs16x8: {
2835                HReg v_dst = newVRegV(env);
2836                HReg v_help = newVRegV(env);
2837                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2838                addInstr(env,
2839                         MIPSInstr_Msa3R(MSA_SUBV, MSA_H, v_help, v_src, v_src));
2840                addInstr(env,
2841                         MIPSInstr_Msa3R(MSA_ADD_A, MSA_H,
2842                                         v_dst, v_src, v_help));
2843                return v_dst;
2844             }
2845 
2846          case Iop_Abs8x16: {
2847                HReg v_dst = newVRegV(env);
2848                HReg v_help = newVRegV(env);
2849                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2850                addInstr(env,
2851                         MIPSInstr_Msa3R(MSA_SUBV, MSA_B, v_help, v_src, v_src));
2852                addInstr(env,
2853                         MIPSInstr_Msa3R(MSA_ADD_A, MSA_B,
2854                                         v_dst, v_src, v_help));
2855                return v_dst;
2856             }
2857 
2858          case Iop_Cnt8x16: {
2859                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2860                HReg res = newVRegV(env);
2861                addInstr(env, MIPSInstr_Msa2R(MSA_PCNT, MSA_B, v_src, res));
2862                return res;
2863             }
2864 
2865          case Iop_NotV128: {
2866                HReg v_dst = newVRegV(env);
2867                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2868                addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_src, v_src));
2869                return v_dst;
2870             }
2871 
2872          case Iop_Reverse8sIn16_x8: {
2873                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2874                HReg v_tmp = newVRegV(env);
2875                addInstr(env,
2876                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2877                addInstr(env,
2878                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2879                return v_src;
2880             }
2881 
2882          case Iop_Reverse8sIn32_x4: {
2883                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2884                HReg v_tmp = newVRegV(env);
2885                addInstr(env,
2886                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_H, v_tmp, v_src, v_src));
2887                addInstr(env,
2888                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_H, v_src, v_tmp, v_src));
2889                addInstr(env,
2890                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2891                addInstr(env,
2892                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2893                return v_src;
2894             }
2895 
2896          case Iop_Reverse8sIn64_x2: {
2897                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2898                HReg v_tmp = newVRegV(env);
2899                addInstr(env,
2900                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_W, v_tmp, v_src, v_src));
2901                addInstr(env,
2902                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_W, v_src, v_tmp, v_src));
2903                addInstr(env,
2904                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_H, v_tmp, v_src, v_src));
2905                addInstr(env,
2906                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_H, v_src, v_tmp, v_src));
2907                addInstr(env,
2908                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2909                addInstr(env,
2910                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2911                return v_src;
2912             }
2913 
2914          case Iop_Cls8x16: {
2915                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2916                HReg v_dst = newVRegV(env);
2917                addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_B, v_src, v_dst));
2918                return v_dst;
2919             }
2920 
2921          case Iop_Cls16x8: {
2922                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2923                HReg v_dst = newVRegV(env);
2924                addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_H, v_src, v_dst));
2925                return v_dst;
2926             }
2927 
2928          case Iop_Cls32x4: {
2929                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2930                HReg v_dst = newVRegV(env);
2931                addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_W, v_src, v_dst));
2932                return v_dst;
2933             }
2934 
2935          case Iop_Clz8x16: {
2936                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2937                HReg v_dst = newVRegV(env);
2938                addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_B, v_src, v_dst));
2939                return v_dst;
2940             }
2941 
2942          case Iop_Clz16x8: {
2943                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2944                HReg v_dst = newVRegV(env);
2945                addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_H, v_src, v_dst));
2946                return v_dst;
2947             }
2948 
2949          case Iop_Clz32x4: {
2950                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2951                HReg v_dst = newVRegV(env);
2952                addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_W, v_src, v_dst));
2953                return v_dst;
2954             }
2955 
2956          case Iop_Clz64x2: {
2957                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2958                HReg v_dst = newVRegV(env);
2959                addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_D, v_src, v_dst));
2960                return v_dst;
2961             }
2962 
2963          case Iop_Abs32Fx4: {
2964                HReg v_src  = iselV128Expr(env, e->Iex.Unop.arg);
2965                HReg v_dst  = newVRegV(env);
2966                HReg v_help = newVRegV(env);
2967                addInstr(env,
2968                         MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_WH,
2969                                          v_help, v_src, v_src));
2970                addInstr(env,
2971                         MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_WH, v_dst, v_help));
2972                return v_dst;
2973             }
2974 
2975          case Iop_Abs64Fx2: {
2976                HReg v_src  = iselV128Expr(env, e->Iex.Unop.arg);
2977                HReg v_dst  = newVRegV(env);
2978                HReg v_help = newVRegV(env);
2979                addInstr(env,
2980                         MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_DW,
2981                                          v_help, v_src, v_src));
2982                addInstr(env,
2983                         MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_DW, v_dst, v_help));
2984                return v_dst;
2985             }
2986 
2987          case Iop_RecipEst32Fx4: {
2988                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2989                HReg v_dst = newVRegV(env);
2990                set_guest_MIPS_rounding_mode_MSA(env);
2991                addInstr(env,
2992                         MIPSInstr_Msa2RF(MSA_FRCP, MSA_F_WH, v_dst, v_src));
2993                set_MIPS_rounding_default_MSA(env);
2994                return v_dst;
2995             }
2996 
2997          case Iop_RecipEst64Fx2: {
2998                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2999                HReg v_dst = newVRegV(env);
3000                set_guest_MIPS_rounding_mode_MSA(env);
3001                addInstr(env,
3002                         MIPSInstr_Msa2RF(MSA_FRCP, MSA_F_DW, v_dst, v_src));
3003                set_MIPS_rounding_default_MSA(env);
3004                return v_dst;
3005             }
3006 
3007          case Iop_RSqrtEst32Fx4: {
3008                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3009                HReg v_dst = newVRegV(env);
3010                set_guest_MIPS_rounding_mode_MSA(env);
3011                addInstr(env,
3012                         MIPSInstr_Msa2RF(MSA_FRSQRT, MSA_F_WH, v_dst, v_src));
3013                set_MIPS_rounding_default_MSA(env);
3014                return v_dst;
3015             }
3016 
3017          case Iop_RSqrtEst64Fx2: {
3018                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3019                HReg v_dst = newVRegV(env);
3020                set_guest_MIPS_rounding_mode_MSA(env);
3021                addInstr(env,
3022                         MIPSInstr_Msa2RF(MSA_FRSQRT, MSA_F_DW, v_dst, v_src));
3023                set_MIPS_rounding_default_MSA(env);
3024                return v_dst;
3025             }
3026 
3027          case Iop_F16toF32x4: {
3028                HReg v_dst = newVRegV(env);
3029 
3030                if (mode64) {
3031                   HReg r_src;
3032                   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3033                   addInstr(env,
3034                            MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src, v_dst));
3035                   addInstr(env,
3036                            MIPSInstr_MsaElm(MSA_INSERT, r_src, v_dst,
3037                                             MSA_DFN_D | 1));
3038                } else {
3039                   HReg r_srch, r_srcl;
3040                   iselInt64Expr(&r_srch, &r_srcl, env, e->Iex.Unop.arg);
3041                   addInstr(env,
3042                            MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_srcl, v_dst));
3043                   addInstr(env,
3044                            MIPSInstr_MsaElm(MSA_INSERT, r_srch, v_dst,
3045                                             MSA_DFN_W | 1));
3046                   addInstr(env,
3047                            MIPSInstr_MsaElm(MSA_INSERT, r_srcl, v_dst,
3048                                             MSA_DFN_W | 2));
3049                   addInstr(env,
3050                            MIPSInstr_MsaElm(MSA_INSERT, r_srch, v_dst,
3051                                             MSA_DFN_W | 3));
3052                }
3053 
3054                addInstr(env,
3055                         MIPSInstr_Msa2RF(MSA_FEXUPR, MSA_F_WH, v_dst, v_dst));
3056                return v_dst;
3057             }
3058 
3059          case Iop_I32UtoFx4: {
3060                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3061                HReg v_dst = newVRegV(env);
3062                set_guest_MIPS_rounding_mode_MSA(env);
3063                addInstr(env,
3064                         MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_WH, v_dst, v_src));
3065                set_MIPS_rounding_default_MSA(env);
3066                return v_dst;
3067             }
3068 
3069          case Iop_FtoI32Sx4_RZ: {
3070                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3071                HReg v_dst = newVRegV(env);
3072                addInstr(env,
3073                         MIPSInstr_Msa2RF(MSA_FTRUNC_S, MSA_F_WH, v_dst, v_src));
3074                return v_dst;
3075             }
3076 
3077          case Iop_FtoI32Ux4_RZ: {
3078                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3079                HReg v_dst = newVRegV(env);
3080                addInstr(env,
3081                         MIPSInstr_Msa2RF(MSA_FTRUNC_U, MSA_F_WH, v_dst, v_src));
3082                return v_dst;
3083             }
3084 
3085          case Iop_Log2_32Fx4: {
3086                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3087                HReg v_dst = newVRegV(env);
3088                addInstr(env,
3089                         MIPSInstr_Msa2RF(MSA_FLOG2, MSA_F_WH, v_dst, v_src));
3090                return v_dst;
3091             }
3092 
3093          case Iop_Log2_64Fx2: {
3094                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3095                HReg v_dst = newVRegV(env);
3096                addInstr(env,
3097                         MIPSInstr_Msa2RF(MSA_FLOG2, MSA_F_DW, v_dst, v_src));
3098                return v_dst;
3099             }
3100          case Iop_CmpNEZ8x16: {
3101                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3102                HReg v_dst = newVRegV(env);
3103                HReg zero = Zero(mode64);
3104                addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3105                addInstr(env,
3106                         MIPSInstr_Msa3R(MSA_CEQ, MSA_B, v_dst, v_src, v_dst));
3107                addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3108                return v_dst;
3109             }
3110          case Iop_CmpNEZ16x8: {
3111                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3112                HReg v_dst = newVRegV(env);
3113                HReg zero = Zero(mode64);
3114                addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3115                addInstr(env,
3116                         MIPSInstr_Msa3R(MSA_CEQ, MSA_H, v_dst, v_src, v_dst));
3117                addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3118                return v_dst;
3119             }
3120           case Iop_CmpNEZ32x4: {
3121                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3122                HReg v_dst = newVRegV(env);
3123                HReg zero = Zero(mode64);
3124                addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3125                addInstr(env,
3126                         MIPSInstr_Msa3R(MSA_CEQ, MSA_W, v_dst, v_src, v_dst));
3127                addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3128                return v_dst;
3129             }
3130           case Iop_CmpNEZ64x2: {
3131                HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3132                HReg v_dst = newVRegV(env);
3133                HReg zero = Zero(mode64);
3134                addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3135                addInstr(env,
3136                         MIPSInstr_Msa3R(MSA_CEQ, MSA_D, v_dst, v_src, v_dst));
3137                addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3138                return v_dst;
3139             }
3140          default:
3141             vex_printf("iselV128Expr_wrk: Unsupported unop: %u\n", op_unop);
3142       }
3143    }
3144 
3145    if (e->tag == Iex_Binop) {
3146       IROp op_binop = e->Iex.Binop.op;
3147 
3148       switch (op_binop) {
3149          case Iop_Add8x16: {
3150                HReg v_dst = newVRegV(env);
3151                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3152                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3153                addInstr(env,
3154                         MIPSInstr_Msa3R(MSA_ADDV, MSA_B,
3155                                         v_dst, v_src1, v_src2));
3156                return v_dst;
3157             }
3158 
3159          case Iop_Add16x8: {
3160                HReg v_dst = newVRegV(env);
3161                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3162                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3163                addInstr(env,
3164                         MIPSInstr_Msa3R(MSA_ADDV, MSA_H,
3165                                         v_dst, v_src1, v_src2));
3166                return v_dst;
3167             }
3168 
3169          case Iop_Add32x4: {
3170                HReg v_dst = newVRegV(env);
3171                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3172                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3173                addInstr(env,
3174                         MIPSInstr_Msa3R(MSA_ADDV, MSA_W,
3175                                         v_dst, v_src1, v_src2));
3176                return v_dst;
3177             }
3178 
3179          case Iop_Add64x2: {
3180                HReg v_dst = newVRegV(env);
3181                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3182                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3183                addInstr(env,
3184                         MIPSInstr_Msa3R(MSA_ADDV, MSA_D,
3185                                         v_dst, v_src1, v_src2));
3186                return v_dst;
3187             }
3188 
3189          case Iop_Sub8x16: {
3190                HReg v_dst = newVRegV(env);
3191                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3192                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3193                addInstr(env,
3194                         MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
3195                                         v_dst, v_src1, v_src2));
3196                return v_dst;
3197             }
3198 
3199          case Iop_Sub16x8: {
3200                HReg v_dst = newVRegV(env);
3201                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3202                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3203                addInstr(env,
3204                         MIPSInstr_Msa3R(MSA_SUBV, MSA_H,
3205                                         v_dst, v_src1, v_src2));
3206                return v_dst;
3207             }
3208 
3209          case Iop_Sub32x4: {
3210                HReg v_dst = newVRegV(env);
3211                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3212                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3213                addInstr(env,
3214                         MIPSInstr_Msa3R(MSA_SUBV, MSA_W,
3215                                         v_dst, v_src1, v_src2));
3216                return v_dst;
3217             }
3218 
3219          case Iop_Sub64x2: {
3220                HReg v_dst = newVRegV(env);
3221                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3222                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3223                addInstr(env,
3224                         MIPSInstr_Msa3R(MSA_SUBV, MSA_D,
3225                                         v_dst, v_src1, v_src2));
3226                return v_dst;
3227             }
3228 
3229          case Iop_QAdd8Sx16: {
3230                HReg v_dst = newVRegV(env);
3231                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3232                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3233                addInstr(env,
3234                         MIPSInstr_Msa3R(MSA_ADDS_S, MSA_B,
3235                                         v_dst, v_src1, v_src2));
3236                return v_dst;
3237             }
3238 
3239          case Iop_QAdd16Sx8: {
3240                HReg v_dst = newVRegV(env);
3241                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3242                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3243                addInstr(env,
3244                         MIPSInstr_Msa3R(MSA_ADDS_S, MSA_H,
3245                                         v_dst, v_src1, v_src2));
3246                return v_dst;
3247             }
3248 
3249          case Iop_QAdd32Sx4: {
3250                HReg v_dst = newVRegV(env);
3251                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3252                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3253                addInstr(env,
3254                         MIPSInstr_Msa3R(MSA_ADDS_S, MSA_W,
3255                                         v_dst, v_src1, v_src2));
3256                return v_dst;
3257             }
3258 
3259          case Iop_QAdd64Sx2: {
3260                HReg v_dst = newVRegV(env);
3261                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3262                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3263                addInstr(env,
3264                         MIPSInstr_Msa3R(MSA_ADDS_S, MSA_D,
3265                                         v_dst, v_src1, v_src2));
3266                return v_dst;
3267             }
3268 
3269          case Iop_QAdd8Ux16: {
3270                HReg v_dst = newVRegV(env);
3271                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3272                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3273                addInstr(env,
3274                         MIPSInstr_Msa3R(MSA_ADDS_U, MSA_B,
3275                                         v_dst, v_src1, v_src2));
3276                return v_dst;
3277             }
3278 
3279          case Iop_QAdd16Ux8: {
3280                HReg v_dst = newVRegV(env);
3281                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3282                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3283                addInstr(env,
3284                         MIPSInstr_Msa3R(MSA_ADDS_U, MSA_H,
3285                                         v_dst, v_src1, v_src2));
3286                return v_dst;
3287             }
3288 
3289          case Iop_QAdd32Ux4: {
3290                HReg v_dst = newVRegV(env);
3291                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3292                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3293                addInstr(env,
3294                         MIPSInstr_Msa3R(MSA_ADDS_U, MSA_W,
3295                                         v_dst, v_src1, v_src2));
3296                return v_dst;
3297             }
3298 
3299          case Iop_QAdd64Ux2: {
3300                HReg v_dst = newVRegV(env);
3301                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3302                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3303                addInstr(env,
3304                         MIPSInstr_Msa3R(MSA_ADDS_U, MSA_D,
3305                                         v_dst, v_src1, v_src2));
3306                return v_dst;
3307             }
3308 
3309          case Iop_QSub8Sx16: {
3310                HReg v_dst = newVRegV(env);
3311                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3312                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3313                addInstr(env,
3314                         MIPSInstr_Msa3R(MSA_SUBS_S, MSA_B,
3315                                         v_dst, v_src1, v_src2));
3316                return v_dst;
3317             }
3318 
3319          case Iop_QSub16Sx8: {
3320                HReg v_dst = newVRegV(env);
3321                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3322                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3323                addInstr(env,
3324                         MIPSInstr_Msa3R(MSA_SUBS_S, MSA_H,
3325                                         v_dst, v_src1, v_src2));
3326                return v_dst;
3327             }
3328 
3329          case Iop_QSub32Sx4: {
3330                HReg v_dst = newVRegV(env);
3331                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3332                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3333                addInstr(env,
3334                         MIPSInstr_Msa3R(MSA_SUBS_S, MSA_W,
3335                                         v_dst, v_src1, v_src2));
3336                return v_dst;
3337             }
3338 
3339          case Iop_QSub64Sx2: {
3340                HReg v_dst = newVRegV(env);
3341                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3342                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3343                addInstr(env,
3344                         MIPSInstr_Msa3R(MSA_SUBS_S, MSA_D,
3345                                         v_dst, v_src1, v_src2));
3346                return v_dst;
3347             }
3348 
3349          case Iop_QSub8Ux16: {
3350                HReg v_dst = newVRegV(env);
3351                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3352                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3353                addInstr(env,
3354                         MIPSInstr_Msa3R(MSA_SUBS_U, MSA_B,
3355                                         v_dst, v_src1, v_src2));
3356                return v_dst;
3357             }
3358 
3359          case Iop_QSub16Ux8: {
3360                HReg v_dst = newVRegV(env);
3361                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3362                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3363                addInstr(env,
3364                         MIPSInstr_Msa3R(MSA_SUBS_U, MSA_H,
3365                                         v_dst, v_src1, v_src2));
3366                return v_dst;
3367             }
3368 
3369          case Iop_QSub32Ux4: {
3370                HReg v_dst = newVRegV(env);
3371                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3372                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3373                addInstr(env,
3374                         MIPSInstr_Msa3R(MSA_SUBS_U, MSA_W,
3375                                         v_dst, v_src1, v_src2));
3376                return v_dst;
3377             }
3378 
3379          case Iop_QSub64Ux2: {
3380                HReg v_dst = newVRegV(env);
3381                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3382                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3383                addInstr(env,
3384                         MIPSInstr_Msa3R(MSA_SUBS_U, MSA_D,
3385                                         v_dst, v_src1, v_src2));
3386                return v_dst;
3387             }
3388 
3389          case Iop_QDMulHi32Sx4: {
3390                HReg v_dst = newVRegV(env);
3391                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3392                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3393                addInstr(env,
3394                         MIPSInstr_Msa3RF(MSA_MUL_Q, MSA_F_DW,
3395                                          v_dst, v_src1, v_src2));
3396                return v_dst;
3397             }
3398 
3399          case Iop_QDMulHi16Sx8: {
3400                HReg v_dst = newVRegV(env);
3401                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3402                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3403                addInstr(env,
3404                         MIPSInstr_Msa3RF(MSA_MUL_Q, MSA_F_WH,
3405                                          v_dst, v_src1, v_src2));
3406                return v_dst;
3407             }
3408 
3409          case Iop_QRDMulHi32Sx4: {
3410                HReg v_dst = newVRegV(env);
3411                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3412                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3413                addInstr(env,
3414                         MIPSInstr_Msa3RF(MSA_MULR_Q, MSA_F_DW,
3415                                          v_dst, v_src1, v_src2));
3416                return v_dst;
3417             }
3418 
3419          case Iop_QRDMulHi16Sx8: {
3420                HReg v_dst = newVRegV(env);
3421                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3422                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3423                addInstr(env,
3424                         MIPSInstr_Msa3RF(MSA_MULR_Q, MSA_F_WH,
3425                                          v_dst, v_src1, v_src2));
3426                return v_dst;
3427             }
3428 
3429          case Iop_Max8Sx16: {
3430                HReg v_dst = newVRegV(env);
3431                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3432                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3433                addInstr(env,
3434                         MIPSInstr_Msa3R(MSA_MAX_S, MSA_B,
3435                                         v_dst, v_src1, v_src2));
3436                return v_dst;
3437             }
3438 
3439          case Iop_Max16Sx8: {
3440                HReg v_dst = newVRegV(env);
3441                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3442                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3443                addInstr(env,
3444                         MIPSInstr_Msa3R(MSA_MAX_S, MSA_H,
3445                                         v_dst, v_src1, v_src2));
3446                return v_dst;
3447             }
3448 
3449          case Iop_Max32Sx4: {
3450                HReg v_dst = newVRegV(env);
3451                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3452                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3453                addInstr(env,
3454                         MIPSInstr_Msa3R(MSA_MAX_S, MSA_W,
3455                                         v_dst, v_src1, v_src2));
3456                return v_dst;
3457             }
3458 
3459          case Iop_Max64Sx2: {
3460                HReg v_dst = newVRegV(env);
3461                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3462                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3463                addInstr(env,
3464                         MIPSInstr_Msa3R(MSA_MAX_S, MSA_D,
3465                                         v_dst, v_src1, v_src2));
3466                return v_dst;
3467             }
3468 
3469          case Iop_Max8Ux16: {
3470                HReg v_dst = newVRegV(env);
3471                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3472                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3473                addInstr(env,
3474                         MIPSInstr_Msa3R(MSA_MAX_U, MSA_B,
3475                                         v_dst, v_src1, v_src2));
3476                return v_dst;
3477             }
3478 
3479          case Iop_Max16Ux8: {
3480                HReg v_dst = newVRegV(env);
3481                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3482                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3483                addInstr(env,
3484                         MIPSInstr_Msa3R(MSA_MAX_U, MSA_H,
3485                                         v_dst, v_src1, v_src2));
3486                return v_dst;
3487             }
3488 
3489          case Iop_Max32Ux4: {
3490                HReg v_dst = newVRegV(env);
3491                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3492                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3493                addInstr(env,
3494                         MIPSInstr_Msa3R(MSA_MAX_U, MSA_W,
3495                                         v_dst, v_src1, v_src2));
3496                return v_dst;
3497             }
3498 
3499          case Iop_Max64Ux2: {
3500                HReg v_dst = newVRegV(env);
3501                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3502                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3503                addInstr(env,
3504                         MIPSInstr_Msa3R(MSA_MAX_U, MSA_D,
3505                                         v_dst, v_src1, v_src2));
3506                return v_dst;
3507             }
3508 
3509          case Iop_Min8Sx16: {
3510                HReg v_dst = newVRegV(env);
3511                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3512                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3513                addInstr(env,
3514                         MIPSInstr_Msa3R(MSA_MIN_S, MSA_B,
3515                                         v_dst, v_src1, v_src2));
3516                return v_dst;
3517             }
3518 
3519          case Iop_Min16Sx8: {
3520                HReg v_dst = newVRegV(env);
3521                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3522                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3523                addInstr(env,
3524                         MIPSInstr_Msa3R(MSA_MIN_S, MSA_H,
3525                                         v_dst, v_src1, v_src2));
3526                return v_dst;
3527             }
3528 
3529          case Iop_Min32Sx4: {
3530                HReg v_dst = newVRegV(env);
3531                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3532                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3533                addInstr(env,
3534                         MIPSInstr_Msa3R(MSA_MIN_S, MSA_W,
3535                                         v_dst, v_src1, v_src2));
3536                return v_dst;
3537             }
3538 
3539          case Iop_Min64Sx2: {
3540                HReg v_dst = newVRegV(env);
3541                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3542                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3543                addInstr(env,
3544                         MIPSInstr_Msa3R(MSA_MIN_S, MSA_D,
3545                                         v_dst, v_src1, v_src2));
3546                return v_dst;
3547             }
3548 
3549          case Iop_Min8Ux16: {
3550                HReg v_dst = newVRegV(env);
3551                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3552                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3553                addInstr(env,
3554                         MIPSInstr_Msa3R(MSA_MIN_U, MSA_B,
3555                                         v_dst, v_src1, v_src2));
3556                return v_dst;
3557             }
3558 
3559          case Iop_Min16Ux8: {
3560                HReg v_dst = newVRegV(env);
3561                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3562                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3563                addInstr(env,
3564                         MIPSInstr_Msa3R(MSA_MIN_U, MSA_H,
3565                                         v_dst, v_src1, v_src2));
3566                return v_dst;
3567             }
3568 
3569          case Iop_Min32Ux4: {
3570                HReg v_dst = newVRegV(env);
3571                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3572                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3573                addInstr(env,
3574                         MIPSInstr_Msa3R(MSA_MIN_U, MSA_W,
3575                                         v_dst, v_src1, v_src2));
3576                return v_dst;
3577             }
3578 
3579          case Iop_Min64Ux2: {
3580                HReg v_dst = newVRegV(env);
3581                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3582                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3583                addInstr(env,
3584                         MIPSInstr_Msa3R(MSA_MIN_U, MSA_D,
3585                                         v_dst, v_src1, v_src2));
3586                return v_dst;
3587             }
3588 
3589          case Iop_Shl8x16: {
3590                HReg v_dst = newVRegV(env);
3591                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3592                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3593                addInstr(env,
3594                         MIPSInstr_Msa3R(MSA_SLL, MSA_B, v_dst, v_src1, v_src2));
3595                return v_dst;
3596             }
3597 
3598          case Iop_Shl16x8: {
3599                HReg v_dst = newVRegV(env);
3600                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3601                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3602                addInstr(env,
3603                         MIPSInstr_Msa3R(MSA_SLL, MSA_H, v_dst, v_src1, v_src2));
3604                return v_dst;
3605             }
3606 
3607          case Iop_Shl32x4: {
3608                HReg v_dst = newVRegV(env);
3609                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3610                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3611                addInstr(env,
3612                         MIPSInstr_Msa3R(MSA_SLL, MSA_W, v_dst, v_src1, v_src2));
3613                return v_dst;
3614             }
3615 
3616          case Iop_Shl64x2: {
3617                HReg v_dst = newVRegV(env);
3618                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3619                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3620                addInstr(env,
3621                         MIPSInstr_Msa3R(MSA_SLL, MSA_D, v_dst, v_src1, v_src2));
3622                return v_dst;
3623             }
3624 
3625          case Iop_Shr8x16: {
3626                HReg v_dst = newVRegV(env);
3627                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3628                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3629                addInstr(env,
3630                         MIPSInstr_Msa3R(MSA_SRL, MSA_B, v_dst, v_src1, v_src2));
3631                return v_dst;
3632             }
3633 
3634          case Iop_Shr16x8: {
3635                HReg v_dst = newVRegV(env);
3636                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3637                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3638                addInstr(env,
3639                         MIPSInstr_Msa3R(MSA_SRL, MSA_H,  v_dst, v_src1, v_src2));
3640                return v_dst;
3641             }
3642 
3643          case Iop_Shr32x4: {
3644                HReg v_dst = newVRegV(env);
3645                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3646                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3647                addInstr(env,
3648                         MIPSInstr_Msa3R(MSA_SRL, MSA_W, v_dst, v_src1, v_src2));
3649                return v_dst;
3650             }
3651 
3652          case Iop_Shr64x2: {
3653                HReg v_dst = newVRegV(env);
3654                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3655                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3656                addInstr(env,
3657                         MIPSInstr_Msa3R(MSA_SRL, MSA_D, v_dst, v_src1, v_src2));
3658                return v_dst;
3659             }
3660 
3661          case Iop_Sar8x16: {
3662                HReg v_dst = newVRegV(env);
3663                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3664                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3665                addInstr(env,
3666                         MIPSInstr_Msa3R(MSA_SRA, MSA_B, v_dst, v_src1, v_src2));
3667                return v_dst;
3668             }
3669 
3670          case Iop_Sar16x8: {
3671                HReg v_dst = newVRegV(env);
3672                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3673                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3674                addInstr(env,
3675                         MIPSInstr_Msa3R(MSA_SRA, MSA_H, v_dst, v_src1, v_src2));
3676                return v_dst;
3677             }
3678 
3679          case Iop_Sar32x4: {
3680                HReg v_dst = newVRegV(env);
3681                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3682                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3683                addInstr(env,
3684                         MIPSInstr_Msa3R(MSA_SRA, MSA_W, v_dst, v_src1, v_src2));
3685                return v_dst;
3686             }
3687 
3688          case Iop_Sar64x2: {
3689                HReg v_dst = newVRegV(env);
3690                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3691                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3692                addInstr(env,
3693                         MIPSInstr_Msa3R(MSA_SRA, MSA_D, v_dst, v_src1, v_src2));
3694                return v_dst;
3695             }
3696 
3697          case Iop_InterleaveHI8x16: {
3698                HReg v_dst = newVRegV(env);
3699                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3700                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3701                addInstr(env,
3702                         MIPSInstr_Msa3R(MSA_ILVL, MSA_B, v_dst, v_src1, v_src2));
3703                return v_dst;
3704             }
3705 
3706          case Iop_InterleaveHI16x8: {
3707                HReg v_dst = newVRegV(env);
3708                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3709                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3710                addInstr(env,
3711                         MIPSInstr_Msa3R(MSA_ILVL, MSA_H,
3712                                         v_dst, v_src1, v_src2));
3713                return v_dst;
3714             }
3715 
3716          case Iop_InterleaveHI32x4: {
3717                HReg v_dst = newVRegV(env);
3718                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3719                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3720                addInstr(env,
3721                         MIPSInstr_Msa3R(MSA_ILVL, MSA_W,
3722                                         v_dst, v_src1, v_src2));
3723                return v_dst;
3724             }
3725 
3726          case Iop_InterleaveHI64x2: {
3727                HReg v_dst = newVRegV(env);
3728                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3729                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3730                addInstr(env,
3731                         MIPSInstr_Msa3R(MSA_ILVL, MSA_D,
3732                                         v_dst, v_src1, v_src2));
3733                return v_dst;
3734             }
3735 
3736          case Iop_InterleaveLO8x16: {
3737                HReg v_dst = newVRegV(env);
3738                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3739                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3740                addInstr(env,
3741                         MIPSInstr_Msa3R(MSA_ILVR, MSA_B,
3742                                         v_dst, v_src1, v_src2));
3743                return v_dst;
3744             }
3745 
3746          case Iop_InterleaveLO16x8: {
3747                HReg v_dst = newVRegV(env);
3748                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3749                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3750                addInstr(env,
3751                         MIPSInstr_Msa3R(MSA_ILVR, MSA_H,
3752                                         v_dst, v_src1, v_src2));
3753                return v_dst;
3754             }
3755 
3756          case Iop_InterleaveLO32x4: {
3757                HReg v_dst = newVRegV(env);
3758                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3759                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3760                addInstr(env,
3761                         MIPSInstr_Msa3R(MSA_ILVR, MSA_W,
3762                                         v_dst, v_src1, v_src2));
3763                return v_dst;
3764             }
3765 
3766          case Iop_InterleaveLO64x2: {
3767                HReg v_dst = newVRegV(env);
3768                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3769                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3770                addInstr(env,
3771                         MIPSInstr_Msa3R(MSA_ILVR, MSA_D,
3772                                         v_dst, v_src1, v_src2));
3773                return v_dst;
3774             }
3775 
3776          case Iop_InterleaveEvenLanes8x16: {
3777                HReg v_dst = newVRegV(env);
3778                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3779                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3780                addInstr(env,
3781                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_B,
3782                                         v_dst, v_src1, v_src2));
3783                return v_dst;
3784             }
3785 
3786          case Iop_InterleaveEvenLanes16x8: {
3787                HReg v_dst = newVRegV(env);
3788                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3789                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3790                addInstr(env,
3791                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_H,
3792                                         v_dst, v_src1, v_src2));
3793                return v_dst;
3794             }
3795 
3796          case Iop_InterleaveEvenLanes32x4: {
3797                HReg v_dst = newVRegV(env);
3798                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3799                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3800                addInstr(env,
3801                         MIPSInstr_Msa3R(MSA_ILVEV, MSA_W,
3802                                         v_dst, v_src1, v_src2));
3803                return v_dst;
3804             }
3805 
3806          case Iop_InterleaveOddLanes8x16: {
3807                HReg v_dst = newVRegV(env);
3808                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3809                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3810                addInstr(env,
3811                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_B,
3812                                         v_dst, v_src1, v_src2));
3813                return v_dst;
3814             }
3815 
3816          case Iop_InterleaveOddLanes16x8: {
3817                HReg v_dst = newVRegV(env);
3818                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3819                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3820                addInstr(env,
3821                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_H,
3822                                         v_dst, v_src1, v_src2));
3823                return v_dst;
3824             }
3825 
3826          case Iop_InterleaveOddLanes32x4: {
3827                HReg v_dst = newVRegV(env);
3828                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3829                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3830                addInstr(env,
3831                         MIPSInstr_Msa3R(MSA_ILVOD, MSA_W,
3832                                         v_dst, v_src1, v_src2));
3833                return v_dst;
3834             }
3835 
3836           case Iop_PackEvenLanes8x16: {
3837                HReg v_dst = newVRegV(env);
3838                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3839                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3840                addInstr(env,
3841                         MIPSInstr_Msa3R(MSA_PCKEV, MSA_B,
3842                                         v_dst, v_src1, v_src2));
3843                return v_dst;
3844             }
3845 
3846          case Iop_PackEvenLanes16x8: {
3847                HReg v_dst = newVRegV(env);
3848                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3849                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3850                addInstr(env,
3851                         MIPSInstr_Msa3R(MSA_PCKEV, MSA_H,
3852                                         v_dst, v_src1, v_src2));
3853                return v_dst;
3854             }
3855 
3856          case Iop_PackEvenLanes32x4: {
3857                HReg v_dst = newVRegV(env);
3858                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3859                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3860                addInstr(env,
3861                         MIPSInstr_Msa3R(MSA_PCKEV, MSA_W,
3862                                         v_dst, v_src1, v_src2));
3863                return v_dst;
3864             }
3865 
3866          case Iop_PackOddLanes8x16: {
3867                HReg v_dst = newVRegV(env);
3868                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3869                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3870                addInstr(env,
3871                         MIPSInstr_Msa3R(MSA_PCKOD, MSA_B,
3872                                         v_dst, v_src1, v_src2));
3873                return v_dst;
3874             }
3875 
3876          case Iop_PackOddLanes16x8: {
3877                HReg v_dst = newVRegV(env);
3878                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3879                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3880                addInstr(env,
3881                         MIPSInstr_Msa3R(MSA_PCKOD, MSA_H,
3882                                         v_dst, v_src1, v_src2));
3883                return v_dst;
3884             }
3885 
3886          case Iop_PackOddLanes32x4: {
3887                HReg v_dst = newVRegV(env);
3888                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3889                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3890                addInstr(env,
3891                         MIPSInstr_Msa3R(MSA_PCKOD, MSA_W,
3892                                         v_dst, v_src1, v_src2));
3893                return v_dst;
3894             }
3895 
3896          case Iop_CmpEQ8x16: {
3897                HReg v_dst = newVRegV(env);
3898                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3899                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3900                addInstr(env,
3901                         MIPSInstr_Msa3R(MSA_CEQ, MSA_B, v_dst, v_src1, v_src2));
3902                return v_dst;
3903             }
3904 
3905          case Iop_CmpEQ16x8: {
3906                HReg v_dst = newVRegV(env);
3907                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3908                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3909                addInstr(env,
3910                         MIPSInstr_Msa3R(MSA_CEQ, MSA_H, v_dst, v_src1, v_src2));
3911                return v_dst;
3912             }
3913 
3914          case Iop_CmpEQ32x4: {
3915                HReg v_dst = newVRegV(env);
3916                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3917                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3918                addInstr(env,
3919                         MIPSInstr_Msa3R(MSA_CEQ, MSA_W, v_dst, v_src1, v_src2));
3920                return v_dst;
3921             }
3922 
3923          case Iop_CmpEQ64x2: {
3924                HReg v_dst = newVRegV(env);
3925                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3926                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3927                addInstr(env,
3928                         MIPSInstr_Msa3R(MSA_CEQ, MSA_D, v_dst, v_src1, v_src2));
3929                return v_dst;
3930             }
3931 
3932          case Iop_CmpGT8Sx16: {
3933                HReg v_dst = newVRegV(env);
3934                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3935                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3936                addInstr(env,
3937                         MIPSInstr_Msa3R(MSA_CLT_S, MSA_B,
3938                                         v_dst, v_src2, v_src1));
3939                return v_dst;
3940             }
3941 
3942          case Iop_CmpGT16Sx8: {
3943                HReg v_dst = newVRegV(env);
3944                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3945                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3946                addInstr(env,
3947                         MIPSInstr_Msa3R(MSA_CLT_S, MSA_H,
3948                                         v_dst, v_src2, v_src1));
3949                return v_dst;
3950             }
3951 
3952          case Iop_CmpGT32Sx4: {
3953                HReg v_dst = newVRegV(env);
3954                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3955                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3956                addInstr(env,
3957                         MIPSInstr_Msa3R(MSA_CLT_S, MSA_W,
3958                                         v_dst, v_src2, v_src1));
3959                return v_dst;
3960             }
3961 
3962          case Iop_CmpGT64Sx2: {
3963                HReg v_dst = newVRegV(env);
3964                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3965                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3966                addInstr(env,
3967                         MIPSInstr_Msa3R(MSA_CLT_S, MSA_D,
3968                                         v_dst, v_src2, v_src1));
3969                return v_dst;
3970             }
3971 
3972          case Iop_CmpGT8Ux16: {
3973                HReg v_dst = newVRegV(env);
3974                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3975                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3976                addInstr(env,
3977                         MIPSInstr_Msa3R(MSA_CLT_U, MSA_B,
3978                                         v_dst, v_src2, v_src1));
3979                return v_dst;
3980             }
3981 
3982          case Iop_CmpGT16Ux8: {
3983                HReg v_dst = newVRegV(env);
3984                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3985                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3986                addInstr(env,
3987                         MIPSInstr_Msa3R(MSA_CLT_U, MSA_H,
3988                                         v_dst, v_src2, v_src1));
3989                return v_dst;
3990             }
3991 
3992          case Iop_CmpGT32Ux4: {
3993                HReg v_dst = newVRegV(env);
3994                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3995                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3996                addInstr(env,
3997                         MIPSInstr_Msa3R(MSA_CLT_U, MSA_W,
3998                                         v_dst, v_src2, v_src1));
3999                return v_dst;
4000             }
4001 
4002          case Iop_CmpGT64Ux2: {
4003                HReg v_dst = newVRegV(env);
4004                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4005                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4006                addInstr(env,
4007                         MIPSInstr_Msa3R(MSA_CLT_U, MSA_D,
4008                                         v_dst, v_src2, v_src1));
4009                return v_dst;
4010             }
4011 
4012          case Iop_Avg8Sx16: {
4013                HReg v_dst = newVRegV(env);
4014                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4015                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4016                addInstr(env,
4017                         MIPSInstr_Msa3R(MSA_AVER_S, MSA_B,
4018                                         v_dst, v_src1, v_src2));
4019                return v_dst;
4020             }
4021 
4022          case Iop_Avg16Sx8: {
4023                HReg v_dst = newVRegV(env);
4024                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4025                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4026                addInstr(env,
4027                         MIPSInstr_Msa3R(MSA_AVER_S, MSA_H,
4028                                         v_dst, v_src1, v_src2));
4029                return v_dst;
4030             }
4031 
4032          case Iop_Avg32Sx4: {
4033                HReg v_dst = newVRegV(env);
4034                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4035                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4036                addInstr(env,
4037                         MIPSInstr_Msa3R(MSA_AVER_S, MSA_W,
4038                                         v_dst, v_src1, v_src2));
4039                return v_dst;
4040             }
4041 
4042          case Iop_Avg8Ux16: {
4043                HReg v_dst = newVRegV(env);
4044                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4045                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4046                addInstr(env,
4047                         MIPSInstr_Msa3R(MSA_AVER_U, MSA_B,
4048                                         v_dst, v_src1, v_src2));
4049                return v_dst;
4050             }
4051 
4052          case Iop_Avg16Ux8: {
4053                HReg v_dst = newVRegV(env);
4054                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4055                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4056                addInstr(env,
4057                         MIPSInstr_Msa3R(MSA_AVER_U, MSA_H,
4058                                         v_dst, v_src1, v_src2));
4059                return v_dst;
4060             }
4061 
4062          case Iop_Avg32Ux4: {
4063                HReg v_dst = newVRegV(env);
4064                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4065                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4066                addInstr(env,
4067                         MIPSInstr_Msa3R(MSA_AVER_U, MSA_W,
4068                                         v_dst, v_src1, v_src2));
4069                return v_dst;
4070             }
4071 
4072          case Iop_Mul8x16: {
4073                HReg v_dst = newVRegV(env);
4074                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4075                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4076                addInstr(env,
4077                         MIPSInstr_Msa3R(MSA_MULV, MSA_B,
4078                                         v_dst, v_src1, v_src2));
4079                return v_dst;
4080             }
4081 
4082          case Iop_Mul16x8: {
4083                HReg v_dst = newVRegV(env);
4084                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4085                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4086                addInstr(env,
4087                         MIPSInstr_Msa3R(MSA_MULV, MSA_H,
4088                                         v_dst, v_src1, v_src2));
4089                return v_dst;
4090             }
4091 
4092          case Iop_Mul32x4: {
4093                HReg v_dst = newVRegV(env);
4094                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4095                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4096                addInstr(env,
4097                         MIPSInstr_Msa3R(MSA_MULV, MSA_W,
4098                                         v_dst, v_src1, v_src2));
4099                return v_dst;
4100             }
4101 
4102          case Iop_AndV128: {
4103                HReg v_dst = newVRegV(env);
4104                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4105                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4106                addInstr(env, MIPSInstr_MsaVec(MSA_ANDV, v_dst, v_src1, v_src2));
4107                return v_dst;
4108             }
4109 
4110          case Iop_OrV128: {
4111                HReg v_dst = newVRegV(env);
4112                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4113                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4114                addInstr(env, MIPSInstr_MsaVec(MSA_ORV, v_dst, v_src1, v_src2));
4115                return v_dst;
4116             }
4117 
4118          case Iop_XorV128: {
4119                HReg v_dst = newVRegV(env);
4120                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4121                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4122                addInstr(env, MIPSInstr_MsaVec(MSA_XORV, v_dst, v_src1, v_src2));
4123                return v_dst;
4124             }
4125 
4126          case Iop_ShrV128: {
4127                HReg v_dst = newVRegV(env);
4128                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4129                MIPSRH *sm;
4130                sm = iselWordExpr_RH7u(env, e->Iex.Binop.arg2);
4131                addInstr(env,
4132                         MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
4133                                         v_dst, v_src1, v_src1));
4134 
4135                if (sm->tag == Mrh_Imm) {
4136                   int n = (sm->Mrh.Imm.imm16) >> 3;
4137                   addInstr(env,
4138                            MIPSInstr_MsaElm(MSA_SLDI, v_src1, v_dst,
4139                                             MSA_DFN_B | n));
4140                } else {
4141                   HReg v_src2 = sm->Mrh.Reg.reg;
4142                   MIPSRH *ri = MIPSRH_Imm(False, 3);
4143                   HReg r_dst = newVRegI(env);
4144                   addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
4145                                                r_dst, v_src2, ri));
4146                   addInstr(env,
4147                            MIPSInstr_Msa3R(MSA_SLD, MSA_B,
4148                                            v_dst, v_src1, r_dst));
4149                }
4150 
4151                return v_dst;
4152             }
4153 
4154          case Iop_ShlV128: {
4155                HReg v_dst = newVRegV(env);
4156                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4157                MIPSRH *sm;
4158                sm = iselWordExpr_RH7u(env, e->Iex.Binop.arg2);
4159                addInstr(env,
4160                         MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
4161                                         v_dst, v_src1, v_src1));
4162 
4163                if (sm->tag == Mrh_Imm) {
4164                   int n = 16 - ((sm->Mrh.Imm.imm16) >> 3);
4165 
4166                   if (n == 16) n = 0;
4167 
4168                   addInstr(env,
4169                            MIPSInstr_MsaElm(MSA_SLDI, v_dst, v_src1,
4170                                             MSA_DFN_B | n));
4171                } else {
4172                   HReg v_src2 = sm->Mrh.Reg.reg;
4173                   MIPSRH *ri = MIPSRH_Imm(False, 3);
4174                   HReg r_dst = newVRegI(env);
4175                   HReg help = newVRegI(env);
4176                   addInstr(env, MIPSInstr_Alu(Malu_XOR, help, v_src2, sm));
4177                   addInstr(env, MIPSInstr_Alu(Malu_SUB, help, help, sm));
4178                   addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
4179                                                r_dst, help, ri));
4180                   addInstr(env,
4181                            MIPSInstr_Msa3R(MSA_SLD, MSA_B,
4182                                            v_src1, v_dst, r_dst));
4183                }
4184 
4185                return v_src1;
4186             }
4187 
4188          case Iop_ShlN8x16: {
4189                HReg v_dst = newVRegV(env);
4190                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4191                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4192                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4193                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4194                addInstr(env,
4195                         MIPSInstr_MsaBit(MSA_SLLI, MSA_B,
4196                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4197                                          v_src1, v_dst));
4198                return v_dst;
4199             }
4200 
4201          case Iop_ShlN16x8: {
4202                HReg v_dst = newVRegV(env);
4203                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4204                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4205                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4206                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4207                addInstr(env,
4208                         MIPSInstr_MsaBit(MSA_SLLI, MSA_H,
4209                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4210                                          v_src1, v_dst));
4211                return v_dst;
4212             }
4213 
4214          case Iop_ShlN32x4: {
4215                HReg v_dst = newVRegV(env);
4216                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4217                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4218                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4219                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4220                addInstr(env,
4221                         MIPSInstr_MsaBit(MSA_SLLI, MSA_W,
4222                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4223                                          v_src1, v_dst));
4224                return v_dst;
4225             }
4226 
4227          case Iop_ShlN64x2: {
4228                HReg v_dst = newVRegV(env);
4229                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4230                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4231                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4232                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4233                addInstr(env,
4234                         MIPSInstr_MsaBit(MSA_SLLI, MSA_D,
4235                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4236                                          v_src1, v_dst));
4237                return v_dst;
4238             }
4239 
4240          case Iop_SarN8x16: {
4241                HReg v_dst = newVRegV(env);
4242                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4243                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4244                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4245                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4246                addInstr(env,
4247                         MIPSInstr_MsaBit(MSA_SRAI, MSA_B,
4248                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4249                                          v_src1, v_dst));
4250                return v_dst;
4251             }
4252 
4253          case Iop_SarN16x8: {
4254                HReg v_dst = newVRegV(env);
4255                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4256                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4257                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4258                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4259                addInstr(env,
4260                         MIPSInstr_MsaBit(MSA_SRAI, MSA_H,
4261                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4262                                          v_src1, v_dst));
4263                return v_dst;
4264             }
4265 
4266          case Iop_SarN32x4: {
4267                HReg v_dst = newVRegV(env);
4268                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4269                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4270                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4271                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4272                addInstr(env,
4273                         MIPSInstr_MsaBit(MSA_SRAI, MSA_W,
4274                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4275                                          v_src1, v_dst));
4276                return v_dst;
4277             }
4278 
4279          case Iop_SarN64x2: {
4280                HReg v_dst = newVRegV(env);
4281                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4282                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4283                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4284                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4285                addInstr(env,
4286                         MIPSInstr_MsaBit(MSA_SRAI, MSA_D,
4287                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4288                                          v_src1, v_dst));
4289                return v_dst;
4290             }
4291 
4292          case Iop_ShrN8x16: {
4293                HReg v_dst = newVRegV(env);
4294                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4295                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4296                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4297                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4298                addInstr(env,
4299                         MIPSInstr_MsaBit(MSA_SRLI, MSA_B,
4300                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4301                                          v_src1, v_dst));
4302                return v_dst;
4303             }
4304 
4305          case Iop_ShrN16x8: {
4306                HReg v_dst = newVRegV(env);
4307                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4308                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4309                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4310                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4311                addInstr(env,
4312                         MIPSInstr_MsaBit(MSA_SRLI, MSA_H,
4313                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4314                                          v_src1, v_dst));
4315                return v_dst;
4316             }
4317 
4318          case Iop_ShrN32x4: {
4319                HReg v_dst = newVRegV(env);
4320                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4321                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4322                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4323                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4324                addInstr(env,
4325                         MIPSInstr_MsaBit(MSA_SRLI, MSA_W,
4326                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4327                                          v_src1, v_dst));
4328                return v_dst;
4329             }
4330 
4331          case Iop_ShrN64x2: {
4332                HReg v_dst = newVRegV(env);
4333                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4334                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4335                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4336                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4337                addInstr(env,
4338                         MIPSInstr_MsaBit(MSA_SRLI, MSA_D,
4339                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4340                                          v_src1, v_dst));
4341                return v_dst;
4342             }
4343 
4344          case Iop_QandQSarNnarrow64Sto32Sx2: {
4345                HReg v_dst = newVRegV(env);
4346                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4347                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4348                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4349                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4350                addInstr(env,
4351                         MIPSInstr_MsaBit(MSA_SRAI, MSA_D,
4352                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4353                                          v_src1, v_dst));
4354                addInstr(env, MIPSInstr_MsaBit(MSA_SAT_S, MSA_D, 31, v_dst, v_dst));
4355                return v_dst;
4356             }
4357 
4358          case Iop_QandQSarNnarrow32Sto16Sx4: {
4359                HReg v_dst = newVRegV(env);
4360                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4361                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4362                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4363                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4364                addInstr(env,
4365                         MIPSInstr_MsaBit(MSA_SRAI, MSA_W,
4366                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4367                                          v_src1, v_dst));
4368                addInstr(env,
4369                         MIPSInstr_MsaBit(MSA_SAT_S, MSA_W, 15, v_dst, v_dst));
4370                return v_dst;
4371             }
4372 
4373          case Iop_QandQRSarNnarrow64Sto32Sx2: {
4374                HReg v_dst = newVRegV(env);
4375                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4376                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4377                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4378                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4379                addInstr(env,
4380                         MIPSInstr_MsaBit(MSA_SRARI, MSA_D,
4381                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4382                                          v_src1, v_dst));
4383                addInstr(env,
4384                         MIPSInstr_MsaBit(MSA_SAT_S, MSA_D, 31, v_dst, v_dst));
4385                return v_dst;
4386             }
4387 
4388          case Iop_QandQRSarNnarrow32Sto16Sx4: {
4389                HReg v_dst = newVRegV(env);
4390                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4391                vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4392                vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4393                vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4394                addInstr(env,
4395                         MIPSInstr_MsaBit(MSA_SRARI, MSA_W,
4396                                          e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4397                                          v_src1, v_dst));
4398                addInstr(env,
4399                         MIPSInstr_MsaBit(MSA_SAT_S, MSA_W, 15, v_dst, v_dst));
4400                return v_dst;
4401             }
4402 
4403          case Iop_CmpEQ32Fx4: {
4404                HReg v_dst = newVRegV(env);
4405                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4406                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4407                addInstr(env,
4408                         MIPSInstr_Msa3RF(MSA_FCEQ, MSA_F_WH,
4409                                          v_dst, v_src1, v_src2));
4410                return v_dst;
4411             }
4412 
4413          case Iop_CmpEQ64Fx2: {
4414                HReg v_dst = newVRegV(env);
4415                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4416                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4417                addInstr(env,
4418                         MIPSInstr_Msa3RF(MSA_FCEQ, MSA_F_DW,
4419                                          v_dst, v_src1, v_src2));
4420                return v_dst;
4421             }
4422 
4423          case Iop_CmpLT32Fx4: {
4424                HReg v_dst = newVRegV(env);
4425                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4426                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4427                addInstr(env,
4428                         MIPSInstr_Msa3RF(MSA_FCLT, MSA_F_WH,
4429                                          v_dst, v_src1, v_src2));
4430                return v_dst;
4431             }
4432 
4433          case Iop_CmpLT64Fx2: {
4434                HReg v_dst = newVRegV(env);
4435                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4436                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4437                addInstr(env,
4438                         MIPSInstr_Msa3RF(MSA_FCLT, MSA_F_DW,
4439                                          v_dst, v_src1, v_src2));
4440                return v_dst;
4441             }
4442 
4443          case Iop_CmpLE32Fx4: {
4444                HReg v_dst = newVRegV(env);
4445                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4446                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4447                addInstr(env,
4448                         MIPSInstr_Msa3RF(MSA_FCLE, MSA_F_WH,
4449                                          v_dst, v_src1, v_src2));
4450                return v_dst;
4451             }
4452 
4453          case Iop_CmpLE64Fx2: {
4454                HReg v_dst = newVRegV(env);
4455                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4456                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4457                addInstr(env,
4458                         MIPSInstr_Msa3RF(MSA_FCLE, MSA_F_DW,
4459                                          v_dst, v_src1, v_src2));
4460                return v_dst;
4461             }
4462 
4463          case Iop_CmpUN32Fx4: {
4464                HReg v_dst = newVRegV(env);
4465                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4466                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4467                addInstr(env,
4468                         MIPSInstr_Msa3RF(MSA_FCUN, MSA_F_WH,
4469                                          v_dst, v_src1, v_src2));
4470                return v_dst;
4471             }
4472 
4473          case Iop_CmpUN64Fx2: {
4474                HReg v_dst = newVRegV(env);
4475                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4476                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4477                addInstr(env,
4478                         MIPSInstr_Msa3RF(MSA_FCUN, MSA_F_DW,
4479                                          v_dst, v_src1, v_src2));
4480                return v_dst;
4481             }
4482 
4483          case Iop_64HLtoV128: {
4484                HReg v_dst = newVRegV(env);
4485 
4486                if (mode64) {
4487                   HReg r_src1;
4488                   HReg r_src2;
4489                   r_src1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
4490                   r_src2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
4491                   addInstr(env,
4492                            MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src2, v_dst));
4493                   addInstr(env,
4494                            MIPSInstr_MsaElm(MSA_INSERT, r_src1, v_dst,
4495                                             MSA_DFN_D | 1));
4496                } else {
4497                   HReg r_src1h, r_src1l;
4498                   HReg r_src2h, r_src2l;
4499                   iselInt64Expr(&r_src1h, &r_src1l, env, e->Iex.Binop.arg1);
4500                   iselInt64Expr(&r_src2h, &r_src2l, env, e->Iex.Binop.arg2);
4501                   addInstr(env,
4502                            MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_src2l, v_dst));
4503                   addInstr(env,
4504                            MIPSInstr_MsaElm(MSA_INSERT, r_src2h, v_dst,
4505                                             MSA_DFN_W | 1));
4506                   addInstr(env,
4507                            MIPSInstr_MsaElm(MSA_INSERT, r_src1l, v_dst,
4508                                             MSA_DFN_W | 2));
4509                   addInstr(env,
4510                            MIPSInstr_MsaElm(MSA_INSERT, r_src1h, v_dst,
4511                                             MSA_DFN_W | 3));
4512                }
4513 
4514                return v_dst;
4515             }
4516 
4517          case Iop_Min32Fx4: {
4518                HReg v_src1  = iselV128Expr(env, e->Iex.Binop.arg1);
4519                HReg v_src2  = iselV128Expr(env, e->Iex.Binop.arg2);
4520                HReg v_dst = newVRegV(env);
4521                addInstr(env,
4522                         MIPSInstr_Msa3RF(MSA_FMIN, MSA_F_WH,
4523                                          v_dst, v_src1, v_src2));
4524                return v_dst;
4525             }
4526 
4527          case Iop_Min64Fx2: {
4528                HReg v_src1  = iselV128Expr(env, e->Iex.Binop.arg1);
4529                HReg v_src2  = iselV128Expr(env, e->Iex.Binop.arg2);
4530                HReg v_dst = newVRegV(env);
4531                addInstr(env,
4532                         MIPSInstr_Msa3RF(MSA_FMIN, MSA_F_DW,
4533                                          v_dst, v_src1, v_src2));
4534                return v_dst;
4535             }
4536 
4537          case Iop_Max32Fx4: {
4538                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4539                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4540                HReg v_dst  = newVRegV(env);
4541                addInstr(env,
4542                         MIPSInstr_Msa3RF(MSA_FMAX, MSA_F_WH,
4543                                          v_dst, v_src1, v_src2));
4544                return v_dst;
4545             }
4546 
4547          case Iop_Max64Fx2: {
4548                HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4549                HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4550                HReg v_dst  = newVRegV(env);
4551                addInstr(env,
4552                         MIPSInstr_Msa3RF(MSA_FMAX, MSA_F_DW,
4553                                          v_dst, v_src1, v_src2));
4554                return v_dst;
4555             }
4556 
4557          case Iop_Sqrt32Fx4: {
4558                HReg v_src = iselV128Expr(env, e->Iex.Binop.arg2);
4559                HReg v_dst = newVRegV(env);
4560                set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
4561                addInstr(env,
4562                         MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_WH, v_dst, v_src));
4563                set_MIPS_rounding_default_MSA(env);
4564                return v_dst;
4565             }
4566 
4567          case Iop_Sqrt64Fx2: {
4568                HReg v_src = iselV128Expr(env, e->Iex.Binop.arg2);
4569                HReg v_dst = newVRegV(env);
4570                set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
4571                addInstr(env,
4572                         MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_DW, v_dst, v_src));
4573                set_MIPS_rounding_default_MSA(env);
4574                return v_dst;
4575             }
4576 
4577          default:
4578             vex_printf("iselV128Expr_wrk: unsupported binop: %x\n", op_binop);
4579       }
4580    }
4581 
4582    if (e->tag == Iex_Triop) {
4583       IROp op_triop = e->Iex.Triop.details->op;
4584 
4585       switch (op_triop) {
4586          case Iop_Add32Fx4: {
4587                HReg v_dst  = newVRegV(env);
4588                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4589                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4590                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4591                addInstr(env,
4592                         MIPSInstr_Msa3RF(MSA_FADD, MSA_F_WH,
4593                                          v_dst, v_src1, v_src2));
4594                set_MIPS_rounding_default_MSA(env);
4595                return v_dst;
4596             }
4597 
4598          case Iop_Add64Fx2: {
4599                HReg v_dst  = newVRegV(env);
4600                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4601                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4602                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4603                addInstr(env,
4604                         MIPSInstr_Msa3RF(MSA_FADD, MSA_F_DW,
4605                                          v_dst, v_src1, v_src2));
4606                set_MIPS_rounding_default_MSA(env);
4607                return v_dst;
4608             }
4609 
4610          case Iop_Sub32Fx4: {
4611                HReg v_dst  = newVRegV(env);
4612                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4613                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4614                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4615                addInstr(env,
4616                         MIPSInstr_Msa3RF(MSA_FSUB, MSA_F_WH,
4617                                          v_dst, v_src1, v_src2));
4618                set_MIPS_rounding_default_MSA(env);
4619                return v_dst;
4620             }
4621 
4622          case Iop_Sub64Fx2: {
4623                HReg v_dst  = newVRegV(env);
4624                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4625                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4626                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4627                addInstr(env,
4628                         MIPSInstr_Msa3RF(MSA_FSUB, MSA_F_DW,
4629                                          v_dst, v_src1, v_src2));
4630                set_MIPS_rounding_default_MSA(env);
4631                return v_dst;
4632             }
4633 
4634          case Iop_Mul32Fx4: {
4635                HReg v_dst  = newVRegV(env);
4636                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4637                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4638                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4639                addInstr(env,
4640                         MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_WH,
4641                                          v_dst, v_src1, v_src2));
4642                set_MIPS_rounding_default_MSA(env);
4643                return v_dst;
4644             }
4645 
4646          case Iop_Mul64Fx2: {
4647                HReg v_dst  = newVRegV(env);
4648                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4649                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4650                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4651                addInstr(env,
4652                         MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_DW,
4653                                          v_dst, v_src1, v_src2));
4654                set_MIPS_rounding_default_MSA(env);
4655                return v_dst;
4656             }
4657 
4658          case Iop_Div32Fx4: {
4659                HReg v_dst  = newVRegV(env);
4660                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4661                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4662                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4663                addInstr(env,
4664                         MIPSInstr_Msa3RF(MSA_FDIV, MSA_F_WH,
4665                                          v_dst, v_src1, v_src2));
4666                set_MIPS_rounding_default_MSA(env);
4667                return v_dst;
4668             }
4669 
4670          case Iop_Div64Fx2: {
4671                HReg v_dst  = newVRegV(env);
4672                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4673                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4674                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4675                addInstr(env,
4676                         MIPSInstr_Msa3RF(MSA_FDIV, MSA_F_DW,
4677                                          v_dst, v_src1, v_src2));
4678                set_MIPS_rounding_default_MSA(env);
4679                return v_dst;
4680             }
4681 
4682          case Iop_F32x4_2toQ16x8: {
4683                HReg v_dst  = newVRegV(env);
4684                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4685                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4686                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4687                addInstr(env,
4688                         MIPSInstr_Msa3RF(MSA_FTQ, MSA_F_WH,
4689                                          v_dst, v_src1, v_src2));
4690                set_MIPS_rounding_default_MSA(env);
4691                return v_dst;
4692             }
4693 
4694          case Iop_F64x2_2toQ32x4: {
4695                HReg v_dst  = newVRegV(env);
4696                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4697                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4698                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4699                addInstr(env,
4700                         MIPSInstr_Msa3RF(MSA_FTQ, MSA_F_DW,
4701                                          v_dst, v_src1, v_src2));
4702                set_MIPS_rounding_default_MSA(env);
4703                return v_dst;
4704             }
4705 
4706           case Iop_Scale2_32Fx4: {
4707                HReg v_dst  = newVRegV(env);
4708                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4709                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4710                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4711                addInstr(env,
4712                         MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_WH,
4713                                          v_dst, v_src1, v_src2));
4714                set_MIPS_rounding_default_MSA(env);
4715                return v_dst;
4716             }
4717 
4718           case Iop_Scale2_64Fx2: {
4719                HReg v_dst  = newVRegV(env);
4720                HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4721                HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4722                set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4723                addInstr(env,
4724                         MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW,
4725                                          v_dst, v_src1, v_src2));
4726                set_MIPS_rounding_default_MSA(env);
4727                return v_dst;
4728             }
4729 
4730          default:
4731             vex_printf("iselV128Expr_wrk: unsupported triop: %x\n", op_triop);
4732       }
4733    }
4734 
4735    if (e->tag == Iex_Const) {
4736       IRConst *con = e->Iex.Const.con;
4737 
4738       if (con->tag != Ico_V128) {
4739          vpanic("iselV128Expr.const(mips)");
4740       } else {
4741          HReg v_dst = newVRegV(env);
4742          UShort val = con->Ico.V128;
4743          HReg zero = Zero(mode64);
4744 
4745          switch (val) {
4746             case 0:  /* likely */
4747                addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
4748                break;
4749 
4750             default: {
4751                   HReg r_tmp = newVRegI(env);
4752                   UInt i;
4753                   addInstr(env, MIPSInstr_LI(r_tmp, 0xfful));
4754 
4755                   if (val & 1) {
4756                      addInstr(env,
4757                               MIPSInstr_Msa2R(MSA_FILL, MSA_B, r_tmp, v_dst));
4758                   } else {
4759                      addInstr(env,
4760                               MIPSInstr_Msa2R(MSA_FILL, MSA_B, zero, v_dst));
4761                   }
4762 
4763                   for (i = 1; i < 16; i++) {
4764                      val >>= 1;
4765 
4766                      if (val & 1) {
4767                         addInstr(env,
4768                                  MIPSInstr_MsaElm(MSA_INSERT, r_tmp, v_dst,
4769                                                   MSA_DFN_B | i));
4770                      } else {
4771                         addInstr(env,
4772                                  MIPSInstr_MsaElm(MSA_INSERT, zero, v_dst,
4773                                                   MSA_DFN_B | i));
4774                      }
4775                   }
4776 
4777                   break;
4778                }
4779          }
4780 
4781          return v_dst;
4782       }
4783    }
4784 
4785    if (e->tag == Iex_ITE) {
4786       HReg v_dst  = newVRegV(env);
4787       HReg iff    = iselV128Expr(env, e->Iex.ITE.iffalse);
4788       HReg ift    = iselV128Expr(env, e->Iex.ITE.iftrue);
4789       HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
4790       addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_cond, r_cond,
4791                                    MIPSRH_Imm(False, 1)));
4792       addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_cond, v_dst));
4793       addInstr(env,
4794                MIPSInstr_Alu(Malu_ADD, r_cond, r_cond, MIPSRH_Imm(True, 1)));
4795       addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_cond, v_dst, MSA_DFN_W | 2));
4796       addInstr(env, MIPSInstr_Msa3R(MSA_VSHF, MSA_D, v_dst, ift, iff));
4797       return v_dst;
4798    }
4799 
4800    vex_printf("iselV128Expr_wrk: Unsupported tag: %x\n", e->tag);
4801    ppIRExpr(e);
4802    vpanic("iselV128Expr(mips)");
4803 }
4804 
4805 /*---------------------------------------------------------*/
4806 /*--- ISEL: Integer expressions (128 bit)               ---*/
4807 /*---------------------------------------------------------*/
4808 
4809 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
4810    which is returned as the first two parameters.  As with
4811    iselWordExpr_R, these may be either real or virtual regs; in any
4812    case they must not be changed by subsequent code emitted by the
4813    caller.  */
4814 
iselInt128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4815 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4816 {
4817    vassert(env->mode64);
4818    iselInt128Expr_wrk(rHi, rLo, env, e);
4819    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
4820    vassert(hregIsVirtual(*rHi));
4821    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
4822    vassert(hregIsVirtual(*rLo));
4823 }
4824 
4825 /* DO NOT CALL THIS DIRECTLY ! */
iselInt128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4826 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
4827                                IRExpr * e)
4828 {
4829    vassert(e);
4830    vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
4831 
4832    /* read 128-bit IRTemp */
4833    if (e->tag == Iex_RdTmp) {
4834       lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
4835       return;
4836    }
4837 
4838    /* --------- BINARY ops --------- */
4839    if (e->tag == Iex_Binop) {
4840       switch (e->Iex.Binop.op) {
4841          /* 64 x 64 -> 128 multiply */
4842          case Iop_MullU64:
4843          case Iop_MullS64: {
4844             HReg tLo = newVRegI(env);
4845             HReg tHi = newVRegI(env);
4846             Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
4847             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
4848             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
4849 #if (__mips_isa_rev >= 6)
4850             addInstr(env, MIPSInstr_Mulr6(syned, False, True,
4851                                           tLo, r_srcL, r_srcR));
4852             addInstr(env, MIPSInstr_Mulr6(syned, False, False,
4853                                           tHi, r_srcL, r_srcR));
4854 #else
4855             addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
4856             addInstr(env, MIPSInstr_Mfhi(tHi));
4857             addInstr(env, MIPSInstr_Mflo(tLo));
4858 #endif
4859             *rHi = tHi;
4860             *rLo = tLo;
4861             return;
4862          }
4863 
4864          /* 64HLto128(e1,e2) */
4865          case Iop_64HLto128:
4866             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
4867             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
4868             return;
4869 
4870          case Iop_DivModU64to64:
4871          case Iop_DivModS64to64: {
4872             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
4873             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
4874             HReg tLo = newVRegI(env);
4875             HReg tHi = newVRegI(env);
4876             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
4877 #if (__mips_isa_rev >= 6)
4878             addInstr(env, MIPSInstr_Divr6(syned/*Unsigned or Signed */ ,
4879                                           False /*32bit or 64bit div */ ,
4880                                           False /*mod*/,
4881                                           tLo, r_srcL, r_srcR));
4882             addInstr(env, MIPSInstr_Divr6(syned/*Unsigned or Signed */ ,
4883                                           False /*32bit or 64bit div */ ,
4884                                           True /*mod*/,
4885                                           tHi, r_srcL, r_srcR));
4886 #else
4887             addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
4888             addInstr(env, MIPSInstr_Mfhi(tHi));
4889             addInstr(env, MIPSInstr_Mflo(tLo));
4890 #endif
4891             *rHi = tHi;
4892             *rLo = tLo;
4893             return;
4894          }
4895 
4896          default:
4897             break;
4898       }
4899    }
4900    vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
4901    ppIRExpr(e);
4902    vpanic("iselInt128Expr(mips64)");
4903 }
4904 
4905 /*---------------------------------------------------------*/
4906 /*--- ISEL: Integer expressions (64 bit)                ---*/
4907 /*---------------------------------------------------------*/
4908 
4909 /* 32-bit mode ONLY. Compute a 64-bit value into the register
4910  * pair HI, LO. HI and LO must not be changed by subsequent
4911  *  code emitted by the caller. */
4912 
iselInt64Expr(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4913 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4914 {
4915    vassert(!env->mode64);
4916    iselInt64Expr_wrk(rHi, rLo, env, e);
4917    vassert(hregClass(*rHi) == HRcInt32);
4918    vassert(hregIsVirtual(*rHi));
4919    vassert(hregClass(*rLo) == HRcInt32);
4920    vassert(hregIsVirtual(*rLo));
4921 }
4922 
4923 /* DO NOT CALL THIS DIRECTLY ! */
iselInt64Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4924 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4925 {
4926    vassert(e);
4927    vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
4928 
4929    /* read 64-bit IRTemp */
4930    if (e->tag == Iex_RdTmp) {
4931       lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
4932       return;
4933    }
4934    /* 64-bit load */
4935    if (e->tag == Iex_Load) {
4936       HReg tLo = newVRegI(env);
4937       HReg tHi = newVRegI(env);
4938       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
4939       addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
4940       addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
4941       *rHi = tHi;
4942       *rLo = tLo;
4943       return;
4944    }
4945 
4946    /* 64-bit literal */
4947    if (e->tag == Iex_Const) {
4948       ULong w64 = e->Iex.Const.con->Ico.U64;
4949       UInt wHi = toUInt(w64 >> 32);
4950       UInt wLo = toUInt(w64);
4951       HReg tLo = newVRegI(env);
4952       HReg tHi = newVRegI(env);
4953       vassert(e->Iex.Const.con->tag == Ico_U64);
4954 
4955       if (wLo == wHi) {
4956          /* Save a precious Int register in this special case. */
4957          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
4958          *rHi = tLo;
4959          *rLo = tLo;
4960       } else {
4961          addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
4962          addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
4963          *rHi = tHi;
4964          *rLo = tLo;
4965       }
4966 
4967       return;
4968    }
4969 
4970    /* 64-bit GET */
4971    if (e->tag == Iex_Get) {
4972       HReg tLo = newVRegI(env);
4973       HReg tHi = newVRegI(env);
4974 
4975       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
4976                                         GuestStatePointer(mode64));
4977       addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
4978       addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
4979       *rHi = tHi;
4980       *rLo = tLo;
4981       return;
4982    }
4983 
4984    /* 64-bit ITE */
4985    if (e->tag == Iex_ITE) {
4986       vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
4987       HReg expr0Lo, expr0Hi;
4988       HReg expr1Lo, expr1Hi;
4989       HReg desLo  = newVRegI(env);
4990       HReg desHi  = newVRegI(env);
4991       HReg cond = iselWordExpr_R(env, e->Iex.ITE.cond);
4992 
4993       /* expr0Hi:expr0Lo = iffalse */
4994       /* expr1Hi:expr1Lo = iftrue */
4995       iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.ITE.iffalse);
4996       iselInt64Expr(&expr1Hi, &expr1Lo, env, e->Iex.ITE.iftrue);
4997 
4998       /* move desLo, expr0Lo
4999        * move desHi, expr0Hi
5000        * movn desLo, expr1Lo, cond
5001        * movn desHi, expr1Hi, cond */
5002 #if (__mips_isa_rev >= 6)
5003       {
5004         HReg r_temp = newVRegI(env);
5005         addInstr(env, MIPSInstr_MoveCond(MSeleqz, desLo, expr0Lo, cond));
5006         addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, expr1Lo, cond));
5007         addInstr(env, MIPSInstr_Alu(Malu_OR, desLo, desLo, MIPSRH_Reg(r_temp)));
5008 
5009         addInstr(env, MIPSInstr_MoveCond(MSeleqz, desHi, expr0Hi, cond));
5010         addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, expr1Hi, cond));
5011         addInstr(env, MIPSInstr_Alu(Malu_OR, desHi, desHi, MIPSRH_Reg(r_temp)));
5012       }
5013 #else
5014       addInstr(env, mk_iMOVds_RR(desLo, expr0Lo));
5015       addInstr(env, mk_iMOVds_RR(desHi, expr0Hi));
5016       addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desLo, expr1Lo, cond));
5017       addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desHi, expr1Hi, cond));
5018 #endif
5019 
5020       *rHi = desHi;
5021       *rLo = desLo;
5022       return;
5023    }
5024 
5025    if (e->tag == Iex_CCall) {
5026       HReg r_dstH = newVRegI(env);
5027       HReg r_dstL = newVRegI(env);
5028       vassert(e->Iex.CCall.retty == Ity_I64);
5029 
5030       /* Marshal args, do the call, clear stack. */
5031       UInt   addToSp = 0;
5032       RetLoc rloc    = mk_RetLoc_INVALID();
5033       doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
5034                    e->Iex.CCall.retty, e->Iex.CCall.args );
5035 
5036       vassert(is_sane_RetLoc(rloc));
5037       vassert(rloc.pri == RLPri_2Int);
5038       vassert(addToSp == 0);
5039       addInstr(env, mk_iMOVds_RR(r_dstL, hregMIPS_GPR2(False)));
5040       addInstr(env, mk_iMOVds_RR(r_dstH, hregMIPS_GPR3(False)));
5041       *rHi = r_dstH;
5042       *rLo = r_dstL;
5043       return;
5044    }
5045 
5046    /* --------- BINARY ops --------- */
5047    if (e->tag == Iex_Binop) {
5048       IROp op_binop = e->Iex.Binop.op;
5049       switch (op_binop) {
5050          /* 32 x 32 -> 64 multiply */
5051          /* Add64 */
5052          case Iop_Add64: {
5053             HReg xLo, xHi, yLo, yHi, carryBit;
5054 
5055             HReg tHi = newVRegI(env);
5056             HReg tHi1 = newVRegI(env);
5057             HReg tLo = newVRegI(env);
5058 
5059             carryBit = newVRegI(env);
5060 
5061             Bool size32 = True;
5062             MIPSCondCode cc = MIPScc_LO;
5063 
5064             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5065             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5066             addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
5067 
5068             /* Check carry. */
5069             addInstr(env, MIPSInstr_Cmp(False, size32, carryBit, tLo, xLo, cc));
5070 
5071             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi1, xHi, MIPSRH_Reg(yHi)));
5072             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, tHi1,
5073                                         MIPSRH_Reg(carryBit)));
5074 
5075             *rHi = tHi;
5076             *rLo = tLo;
5077             return;
5078          }
5079          case Iop_Sub64: {
5080             HReg xLo, xHi, yLo, yHi, borrow;
5081             Bool size32 = True;
5082             MIPSCondCode cc = MIPScc_LO;
5083 
5084             HReg tHi = newVRegI(env);
5085             HReg tLo = newVRegI(env);
5086 
5087             borrow = newVRegI(env);
5088 
5089             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5090             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5091 
5092             addInstr(env, MIPSInstr_Alu(Malu_SUB, tLo, xLo, MIPSRH_Reg(yLo)));
5093 
5094             /* Check if borrow is nedded. */
5095             addInstr(env, MIPSInstr_Cmp(False, size32, borrow, xLo, yLo, cc));
5096 
5097             addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi,
5098                                         MIPSRH_Reg(borrow)));
5099             addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, xHi, MIPSRH_Reg(yHi)));
5100 
5101             *rHi = tHi;
5102             *rLo = tLo;
5103             return;
5104          }
5105          case Iop_MullU32:
5106          case Iop_MullS32: {
5107             HReg tLo = newVRegI(env);
5108             HReg tHi = newVRegI(env);
5109             Bool syned = toBool(op_binop == Iop_MullS32);
5110             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
5111             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
5112 #if (__mips_isa_rev >= 6)
5113             addInstr(env, MIPSInstr_Mulr6(syned, True, True,
5114                                           tLo, r_srcL, r_srcR));
5115             addInstr(env, MIPSInstr_Mulr6(syned, True, False,
5116                                           tHi, r_srcL, r_srcR));
5117 #else
5118             addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
5119             addInstr(env, MIPSInstr_Mfhi(tHi));
5120             addInstr(env, MIPSInstr_Mflo(tLo));
5121 #endif
5122             *rHi = tHi;
5123             *rLo = tLo;
5124 
5125             return;
5126          }
5127 
5128          case Iop_DivModU32to32:
5129          case Iop_DivModS32to32: {
5130             HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
5131             HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
5132             HReg tLo = newVRegI(env);
5133             HReg tHi = newVRegI(env);
5134             Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS32to32);
5135 
5136 #if (__mips_isa_rev >= 6)
5137             addInstr(env, MIPSInstr_Divr6(syned /*Unsigned or Signed */ ,
5138                                           True /*32bit or 64bit div */ ,
5139                                           False /*mod*/,
5140                                           tLo, r_srcL, r_srcR));
5141             addInstr(env, MIPSInstr_Divr6(syned /*Unsigned or Signed */ ,
5142                                           True /*32bit or 64bit div */ ,
5143                                           True /*mod*/,
5144                                           tHi, r_srcL, r_srcR));
5145 #else
5146             addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
5147             addInstr(env, MIPSInstr_Mfhi(tHi));
5148             addInstr(env, MIPSInstr_Mflo(tLo));
5149 #endif
5150             *rHi = tHi;
5151             *rLo = tLo;
5152             return;
5153          }
5154 
5155          /* 32HLto64(e1,e2) */
5156          case Iop_32HLto64:
5157             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
5158             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
5159 
5160             return;
5161          /* Or64/And64/Xor64 */
5162          case Iop_Or64:
5163          case Iop_And64:
5164          case Iop_Xor64: {
5165             HReg xLo, xHi, yLo, yHi;
5166             HReg tLo = newVRegI(env);
5167             HReg tHi = newVRegI(env);
5168             MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
5169                            (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
5170             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5171             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5172             addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
5173             addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
5174             *rHi = tHi;
5175             *rLo = tLo;
5176             return;
5177          }
5178 
5179          case Iop_Shr64: {
5180             /* 64-bit logical shift right based on what gcc generates:
5181                <shift>:
5182                nor  v0, zero, a2
5183                sll  a3, a1, 0x1
5184                sllv a3, a3, v0
5185                srlv v0, a0, a2
5186                srlv v1, a1, a2
5187                andi a0, a2, 0x20
5188                or   v0, a3, v0
5189                movn v0, v1, a0
5190                jr   ra
5191                movn v1, zero, a0
5192             */
5193             HReg r_srcLo, r_srcHi;
5194             HReg r_srcLotmp = newVRegI(env);
5195             HReg shift = newVRegI(env);
5196             HReg a3 = newVRegI(env);
5197             HReg r_dstLo = newVRegI(env);
5198             HReg r_dstHi = newVRegI(env);
5199             HReg zero = hregMIPS_GPR0(env->mode64);
5200             MIPSRH *sa = NULL;
5201 
5202             iselInt64Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
5203             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5204 
5205             if (sa->tag == Mrh_Imm) {
5206                addInstr(env, MIPSInstr_LI(shift, sa->Mrh.Imm.imm16));
5207             }
5208             else {
5209                addInstr(env, MIPSInstr_Alu(Malu_AND, shift, sa->Mrh.Reg.reg,
5210                                            MIPSRH_Imm(False, 0x3f)));
5211             }
5212             /* nor  r_dstLo, zero, shift */
5213             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(shift)));
5214             /* sll  a3, r_srcHi, 0x1 */
5215             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5216                                          a3, r_srcHi, MIPSRH_Imm(False, 0x1)));
5217             /* sllv a3, a3, r_dstLo */
5218             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5219                                          a3, a3, MIPSRH_Reg(r_dstLo)));
5220             /* srlv r_dstLo, r_srcLo, shift */
5221             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5222                                          r_dstLo, r_srcLo, MIPSRH_Reg(shift)));
5223             /* srlv r_dstHi, r_srcHi, shift */
5224             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5225                                          r_dstHi, r_srcHi, MIPSRH_Reg(shift)));
5226             /* andi r_srcLo, shift, 0x20 */
5227             addInstr(env, MIPSInstr_Alu(Malu_AND, r_srcLotmp, shift,
5228                                         MIPSRH_Imm(False, 0x20)));
5229             /* or   r_dstLo, a3, r_dstLo */
5230             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, a3, MIPSRH_Reg(r_dstLo)));
5231 #if (__mips_isa_rev >= 6)
5232             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, r_srcLotmp));
5233             addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_dstHi, r_srcLotmp));
5234             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, r_dstLo, MIPSRH_Reg(a3)));
5235 
5236             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, r_srcLotmp));
5237 #else
5238             /* movn    r_dstLo, r_dstHi, r_srcLo */
5239             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, r_dstHi, r_srcLotmp));
5240             /* movn    r_dstHi, zero, r_srcLo */
5241             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, zero, r_srcLotmp));
5242 #endif
5243             *rHi = r_dstHi;
5244             *rLo = r_dstLo;
5245             return;
5246          }
5247 
5248          case Iop_Shl64: {
5249             /* 64-bit shift left based on what gcc generates:
5250                <shift>:
5251                nor  v0,zero,a2
5252                srl  a3,a0,0x1
5253                srlv a3,a3,v0
5254                sllv v1,a1,a2
5255                andi v0,a2,0x20
5256                or   v1,a3,v1
5257                sllv a2,a0,a2
5258                movn v1,a2,v0
5259                movn a2,zero,v0
5260                jr   ra
5261                move v0,a2
5262             */
5263             HReg r_srcLo, r_srcHi;
5264             HReg r_shift = newVRegI(env);
5265             HReg a3 = newVRegI(env);
5266             HReg r_dstLo = newVRegI(env);
5267             HReg r_dstHi = newVRegI(env);
5268             HReg zero = hregMIPS_GPR0(env->mode64);
5269             MIPSRH *sa = NULL;
5270 
5271             iselInt64Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
5272             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5273 
5274             if (sa->tag == Mrh_Imm) {
5275                addInstr(env, MIPSInstr_LI(r_shift, sa->Mrh.Imm.imm16));
5276             }
5277             else {
5278                addInstr(env, MIPSInstr_Alu(Malu_AND, r_shift, sa->Mrh.Reg.reg,
5279                                            MIPSRH_Imm(False, 0x3f)));
5280             }
5281             /* nor r_dstLo, zero, r_shift */
5282             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(r_shift)));
5283             /* srl a3, r_srcLo, 0x1 */
5284             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5285                                          a3, r_srcLo, MIPSRH_Imm(False, 0x1)));
5286             /* srlv a3, a3, r_dstLo */
5287             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5288                                          a3, a3, MIPSRH_Reg(r_dstLo)));
5289             /* sllv r_dstHi, r_srcHi, r_shift */
5290             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5291                                          r_dstHi, r_srcHi, MIPSRH_Reg(r_shift)));
5292             /* or r_dstHi, a3, r_dstHi */
5293             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, a3, MIPSRH_Reg(r_dstHi)));
5294             /* andi a3, r_shift, 0x20 */
5295             addInstr(env, MIPSInstr_Alu(Malu_AND, a3, r_shift,
5296                                         MIPSRH_Imm(False, 0x20)));
5297             /* sllv r_dstLo, r_srcLo, r_shift */
5298             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5299                                          r_dstLo, r_srcLo, MIPSRH_Reg(r_shift)));
5300 #if (__mips_isa_rev >= 6)
5301             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, a3));
5302             addInstr(env, MIPSInstr_MoveCond(MSelnez, r_shift, r_dstLo, a3));
5303             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, r_dstHi, MIPSRH_Reg(r_shift)));
5304 
5305             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, a3));
5306 #else
5307             /* movn r_dstHi, r_dstLo, a3 */
5308             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, r_dstLo, a3));
5309             /* movn r_dstLo, zero, a3 */
5310             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, zero, a3));
5311 #endif
5312             *rHi = r_dstHi;
5313             *rLo = r_dstLo;
5314             return;
5315          }
5316 
5317          case Iop_Sar64: {
5318             /* 64-bit arithmetic shift right based on what gcc generates:
5319                <shift>:
5320                nor  v0, zero, a2
5321                sll  a3, a1, 0x1
5322                sllv a3, a3, v0
5323                srlv v0, a0, a2
5324                srav v1, a1, a2
5325                andi a0, a2, 0x20
5326                sra  a1, a1, 0x1f
5327                or   v0, a3, v0
5328                movn v0, v1, a0
5329                jr   ra
5330                movn v1, a1, a0
5331             */
5332             HReg r_srcHi, r_srcLo;
5333             HReg r_srcHitmp = newVRegI(env);
5334             HReg r_srcLotmp = newVRegI(env);
5335             HReg r_shift = newVRegI(env);
5336             HReg a3 = newVRegI(env);
5337             HReg r_dstLo = newVRegI(env);
5338             HReg r_dstHi = newVRegI(env);
5339             HReg zero = hregMIPS_GPR0(env->mode64);
5340             MIPSRH *sa = NULL;
5341 
5342             iselInt64Expr(&r_srcLo, &r_srcHi, env, e->Iex.Binop.arg1);
5343             sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5344 
5345             if (sa->tag == Mrh_Imm) {
5346                addInstr(env, MIPSInstr_LI(r_shift, sa->Mrh.Imm.imm16));
5347             }
5348             else {
5349                addInstr(env, MIPSInstr_Alu(Malu_AND, r_shift, sa->Mrh.Reg.reg,
5350                                            MIPSRH_Imm(False, 0x3f)));
5351             }
5352             /* nor  r_dstLo, zero, r_shift */
5353             addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(r_shift)));
5354             /* sll  a3, r_srcLo, 0x1 */
5355             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5356                                          a3, r_srcLo, MIPSRH_Imm(False, 0x1)));
5357             /* sllv a3, a3, r_dstLo */
5358             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5359                                          a3, a3, MIPSRH_Reg(r_dstLo)));
5360             /* srlv r_dstLo, r_srcHi, r_shift */
5361             addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5362                                          r_dstLo, r_srcHi, MIPSRH_Reg(r_shift)));
5363             /* srav r_dstHi, r_srcLo, r_shift */
5364             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
5365                                          r_dstHi, r_srcLo, MIPSRH_Reg(r_shift)));
5366             /* andi r_srcHi, r_shift, 0x20 */
5367             addInstr(env, MIPSInstr_Alu(Malu_AND, r_srcHitmp, r_shift,
5368                                         MIPSRH_Imm(False, 0x20)));
5369             /* sra r_srcLo, r_srcLo, 0x1f */
5370             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
5371                                          r_srcLotmp, r_srcLo, MIPSRH_Imm(False, 0x1f)));
5372             /* or   r_dstLo, a3, r_dstLo */
5373             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, a3, MIPSRH_Reg(r_dstLo)));
5374 #if (__mips_isa_rev >= 6)
5375             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, r_srcHitmp));
5376             addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_dstHi, r_srcHitmp));
5377             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, r_dstLo, MIPSRH_Reg(a3)));
5378 
5379             addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, r_srcHitmp));
5380             addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_srcLotmp, r_srcHitmp));
5381             addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, r_dstHi, MIPSRH_Reg(a3)));
5382 #else
5383             /* movn    r_dstLo, r_dstHi, r_srcHi */
5384             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, r_dstHi, r_srcHitmp));
5385             /* movn    r_dstHi, r_srcLo, r_srcHi */
5386             addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, r_srcLotmp, r_srcHitmp));
5387 #endif
5388             *rHi = r_dstHi;
5389             *rLo = r_dstLo;
5390             return;
5391          }
5392 
5393          case Iop_F32toI64S: {
5394             HReg tmpD = newVRegD(env);
5395             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
5396             HReg tLo  = newVRegI(env);
5397             HReg tHi  = newVRegI(env);
5398             MIPSAMode *am_addr;
5399 
5400             /* CVTLS tmpD, valF */
5401             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
5402             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
5403             set_MIPS_rounding_default(env);
5404 
5405             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
5406             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5407 
5408             /* store as F64 */
5409             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
5410                                            am_addr));
5411             /* load as 2xI32 */
5412 #if defined (_MIPSEL)
5413             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5414             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5415                                          mode64));
5416 #elif defined (_MIPSEB)
5417             addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5418             addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5419                                          mode64));
5420 #endif
5421 
5422             /* Reset SP */
5423             add_to_sp(env, 16);
5424 
5425             *rHi = tHi;
5426             *rLo = tLo;
5427 
5428             return;
5429          }
5430          case Iop_F64toI64U: {
5431             HReg r_src;
5432             HReg tmp = newVRegV(env);
5433             vassert(has_msa);
5434             r_src = iselDblExpr( env, e->Iex.Binop.arg2);
5435             set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
5436             addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_U, MSA_F_DW, tmp, r_src));
5437             HReg r_dsth = newVRegI(env);
5438             HReg r_dstl = newVRegI(env);
5439             addInstr(env,
5440                      MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_dstl, MSA_DFN_W | 0));
5441             addInstr(env,
5442                      MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_dsth, MSA_DFN_W | 1));
5443             *rHi = r_dsth;
5444             *rLo = r_dstl;
5445             set_MIPS_rounding_default_MSA(env);
5446             return;
5447          }
5448 
5449          case Iop_GetElem64x2: {
5450             vassert(has_msa);
5451             HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
5452             HReg r_dstHI = newVRegI(env);
5453             HReg r_dstLO = newVRegI(env);
5454             MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
5455 
5456             switch (tmp->tag) {
5457                case Mrh_Imm:
5458                   addInstr(env,
5459                            MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dstHI,
5460                                             MSA_DFN_W |
5461                                             (((tmp->Mrh.Imm.imm16 & 0x01) << 1)
5462                                             + 1)));
5463                   addInstr(env,
5464                            MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dstLO,
5465                                             MSA_DFN_W |
5466                                             ((tmp->Mrh.Imm.imm16 & 0x01) << 1)));
5467                   break;
5468 
5469                case Mrh_Reg: {
5470                      HReg v_tmp = newVRegV(env);
5471                      addInstr(env,
5472                               MIPSInstr_Msa3R(MSA_SPLAT, MSA_D, v_tmp, v_src,
5473                                               tmp->Mrh.Reg.reg));
5474                      addInstr(env,
5475                               MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dstHI,
5476                                                MSA_DFN_W | 1));
5477                      addInstr(env,
5478                               MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dstLO,
5479                                                MSA_DFN_W));
5480                      break;
5481                   }
5482             }
5483 
5484             *rHi = r_dstHI;
5485             *rLo = r_dstLO;
5486             return;
5487          }
5488 
5489          case Iop_Mul64: {
5490             HReg a_L, a_H, b_L, b_H;
5491             HReg dst_L = newVRegI(env);
5492             HReg dst_H = newVRegI(env);
5493 
5494             iselInt64Expr(&a_H, &a_L, env, e->Iex.Binop.arg1);
5495             iselInt64Expr(&b_H, &b_L, env, e->Iex.Binop.arg2);
5496 #if (__mips_isa_rev >= 6)
5497             addInstr(env, MIPSInstr_Mulr6(True, True, True,
5498                                           dst_H, a_H, b_L));
5499             addInstr(env, MIPSInstr_Mulr6(True, True, True,
5500                                           dst_L, b_H, a_L));
5501             addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5502                                         MIPSRH_Reg(dst_L)));
5503             addInstr(env, MIPSInstr_Mulr6(False, True, False,
5504                                           dst_L, a_L, b_L));
5505 
5506             addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5507                                         MIPSRH_Reg(dst_L)));
5508             addInstr(env, MIPSInstr_Mulr6(False, True, True,
5509                                           dst_L, a_L, b_L));
5510 #else
5511             addInstr(env, MIPSInstr_Mul(dst_H, a_H, b_L));
5512             addInstr(env, MIPSInstr_Mult(True, b_H, a_L));
5513             addInstr(env, MIPSInstr_Mflo(dst_L));
5514             addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5515                                         MIPSRH_Reg(dst_L)));
5516             addInstr(env, MIPSInstr_Mult(False, a_L, b_L));
5517             addInstr(env, MIPSInstr_Mfhi(dst_L));
5518 
5519             addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5520                                         MIPSRH_Reg(dst_L)));
5521             addInstr(env, MIPSInstr_Mflo(dst_L));
5522 #endif
5523             *rHi = dst_H;
5524             *rLo = dst_L;
5525             return;
5526          }
5527 
5528          case Iop_DivS64: {
5529             HReg src1_L, src1_H, src2_L, src2_H;
5530             HReg dst_L = newVRegI(env);
5531             HReg dst_H = newVRegI(env);
5532             HReg tmp1 = newVRegV(env);
5533             HReg tmp2 = newVRegV(env);
5534             vassert(has_msa);
5535             iselInt64Expr(&src1_H, &src1_L, env, e->Iex.Binop.arg1);
5536             iselInt64Expr(&src2_H, &src2_L, env, e->Iex.Binop.arg2);
5537             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src1_L, tmp1));
5538             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src1_H, tmp1, MSA_DFN_W | 1));
5539             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src2_L, tmp2));
5540             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src2_H, tmp2, MSA_DFN_W | 1));
5541             addInstr(env, MIPSInstr_Msa3R(MSA_DIVS, MSA_D, tmp1, tmp1, tmp2));
5542             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_H, MSA_DFN_W | 1));
5543             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_L, MSA_DFN_W | 0));
5544             *rHi = dst_H;
5545             *rLo = dst_L;
5546             return;
5547          }
5548 
5549          case Iop_DivU64: {
5550             HReg src1_L, src1_H, src2_L, src2_H;
5551             HReg dst_L = newVRegI(env);
5552             HReg dst_H = newVRegI(env);
5553             HReg tmp1 = newVRegV(env);
5554             HReg tmp2 = newVRegV(env);
5555             vassert(has_msa);
5556             iselInt64Expr(&src1_H, &src1_L, env, e->Iex.Binop.arg1);
5557             iselInt64Expr(&src2_H, &src2_L, env, e->Iex.Binop.arg2);
5558             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src1_L, tmp1));
5559             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src1_H, tmp1, MSA_DFN_W | 1));
5560             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src2_L, tmp2));
5561             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src2_H, tmp2, MSA_DFN_W | 1));
5562             addInstr(env, MIPSInstr_Msa3R(MSA_DIVU, MSA_D, tmp1, tmp1, tmp2));
5563             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_H, MSA_DFN_W | 1));
5564             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_L, MSA_DFN_W | 0));
5565             *rHi = dst_H;
5566             *rLo = dst_L;
5567             return;
5568          }
5569 
5570          case Iop_F64toI64S: {
5571             HReg tmpD = newVRegD(env);
5572             HReg valF;
5573             HReg tLo  = newVRegI(env);
5574             HReg tHi  = newVRegI(env);
5575             MIPSAMode *am_addr;
5576 
5577             if(mode64){
5578               valF = iselFltExpr(env, e->Iex.Binop.arg2);
5579             } else {
5580               valF = iselDblExpr(env, e->Iex.Binop.arg2);
5581             }
5582 
5583             /* CVTLS tmpD, valF */
5584             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
5585             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, tmpD, valF));
5586             set_MIPS_rounding_default(env);
5587 
5588             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
5589             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5590 
5591             /* store as F64 */
5592             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
5593                                            am_addr));
5594             /* load as 2xI32 */
5595 #if defined (_MIPSEL)
5596             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5597             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5598                                          mode64));
5599 #elif defined (_MIPSEB)
5600             addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5601             addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5602                                          mode64));
5603 #endif
5604 
5605             /* Reset SP */
5606             add_to_sp(env, 16);
5607 
5608             *rHi = tHi;
5609             *rLo = tLo;
5610 
5611             return;
5612          }
5613 
5614          default:
5615             break;
5616       }
5617    }
5618 
5619    /* --------- UNARY ops --------- */
5620    if (e->tag == Iex_Unop) {
5621       switch (e->Iex.Unop.op) {
5622          case Iop_1Sto64: {
5623             HReg tLo = newVRegI(env);
5624             HReg tHi = newVRegI(env);
5625             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5626             HReg tmp = newVRegI(env);
5627 
5628             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
5629                           MIPSRH_Imm(False, 31)));
5630             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
5631                           MIPSRH_Imm(False, 31)));
5632 
5633             addInstr(env, mk_iMOVds_RR(tHi, tmp));
5634             addInstr(env, mk_iMOVds_RR(tLo, tmp));
5635 
5636             *rHi = tHi;
5637             *rLo = tLo;
5638             return;
5639          }
5640 
5641          case Iop_8Sto64:
5642          case Iop_16Sto64: {
5643             HReg tLo = newVRegI(env);
5644             HReg tHi = newVRegI(env);
5645             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5646             UInt no_bits = (e->Iex.Unop.op == Iop_8Sto64) ? 24 : 16;
5647             addInstr(env, mk_iMOVds_RR(tLo, src));
5648             addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tLo, tLo,
5649                           MIPSRH_Imm(False, no_bits)));
5650             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tLo,
5651                           MIPSRH_Imm(False, 31)));
5652             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tLo, tLo,
5653                           MIPSRH_Imm(False, no_bits)));
5654             addInstr(env, mk_iMOVds_RR(tHi, tLo));
5655             *rHi = tHi;
5656             *rLo = tLo;
5657             return;
5658          }
5659 
5660          /* 32Sto64(e) */
5661          case Iop_32Sto64: {
5662             HReg tLo = newVRegI(env);
5663             HReg tHi = newVRegI(env);
5664             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5665             addInstr(env, mk_iMOVds_RR(tHi, src));
5666             addInstr(env, mk_iMOVds_RR(tLo, src));
5667             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
5668                           MIPSRH_Imm(False, 31)));
5669             *rHi = tHi;
5670             *rLo = tLo;
5671             return;
5672          }
5673 
5674          case Iop_8Uto64:
5675          case Iop_16Uto64: {
5676             HReg tLo = newVRegI(env);
5677             HReg tHi = newVRegI(env);
5678             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5679             UInt mask = (e->Iex.Unop.op == Iop_8Sto64) ? 0xFF : 0xFFFF;
5680             addInstr(env, MIPSInstr_Alu(Malu_AND, tLo, src,
5681                                         MIPSRH_Imm(False, mask)));
5682             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
5683                                         MIPSRH_Reg(hregMIPS_GPR0(mode64))));
5684             *rHi = tHi;
5685             *rLo = tLo;
5686             return;
5687          }
5688 
5689          /* 32Uto64(e) */
5690          case Iop_32Uto64: {
5691             HReg tLo = newVRegI(env);
5692             HReg tHi = newVRegI(env);
5693             HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5694             addInstr(env, mk_iMOVds_RR(tLo, src));
5695             addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
5696                           MIPSRH_Reg(hregMIPS_GPR0(mode64))));
5697             *rHi = tHi;
5698             *rLo = tLo;
5699             return;
5700          }
5701 
5702          case Iop_Left64: {
5703             HReg yHi, yLo;
5704             HReg tHi  = newVRegI(env);
5705             HReg tLo  = newVRegI(env);
5706             HReg tmp  = newVRegI(env);
5707             HReg tmp1  = newVRegI(env);
5708             HReg tmp2  = newVRegI(env);
5709             HReg zero = newVRegI(env);
5710             MIPSCondCode cc = MIPScc_LO;
5711 
5712             /* yHi:yLo = arg */
5713             iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
5714             /* zero = 0 */
5715             addInstr(env, MIPSInstr_LI(zero, 0x00000000));
5716 
5717             /* tmp2:tmp1 = 0 - (yHi:yLo)*/
5718             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, zero, MIPSRH_Reg(yLo)));
5719             addInstr(env, MIPSInstr_Cmp(False, True, tmp1, zero, tmp2, cc));
5720             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, zero, MIPSRH_Reg(yHi)));
5721             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp1, tmp, MIPSRH_Reg(tmp1)));
5722 
5723             /* So now we have tmp2:tmp1 = -arg.  To finish off, or 'arg'
5724                back in, so as to give the final result
5725                tHi:tLo = arg | -arg. */
5726             addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, yHi, MIPSRH_Reg(tmp1)));
5727             addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, yLo, MIPSRH_Reg(tmp2)));
5728             *rHi = tHi;
5729             *rLo = tLo;
5730             return;
5731          }
5732 
5733          case Iop_CmpwNEZ64: {
5734             HReg srcLo, srcHi;
5735             HReg tmp1 = newVRegI(env);
5736             HReg tmp2 = newVRegI(env);
5737             /* srcHi:srcLo = arg */
5738             iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
5739             /* tmp1 = srcHi | srcLo */
5740             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
5741                                         MIPSRH_Reg(srcHi)));
5742             /* tmp2 = (tmp1 | -tmp1) >>s 31 */
5743 
5744             addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
5745                                         MIPSRH_Reg(tmp1)));
5746 
5747             addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
5748             addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
5749                           MIPSRH_Imm(False, 31)));
5750             *rHi = tmp2;
5751             *rLo = tmp2;
5752             return;
5753 
5754          }
5755          case Iop_ReinterpF64asI64: {
5756             HReg tLo = newVRegI(env);
5757             HReg tHi = newVRegI(env);
5758             MIPSAMode *am_addr;
5759             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
5760 
5761             sub_from_sp(env, 16);  /* Move SP down 16 bytes */
5762             am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5763 
5764             /* store as F64 */
5765             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
5766                                            am_addr));
5767             /* load as 2xI32 */
5768 #if defined (_MIPSEL)
5769             addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5770             addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5771                                          mode64));
5772 #elif defined (_MIPSEB)
5773             addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5774             addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5775                                          mode64));
5776 #endif
5777 
5778             /* Reset SP */
5779             add_to_sp(env, 16);
5780 
5781             *rHi = tHi;
5782             *rLo = tLo;
5783             return;
5784          }
5785 
5786          case Iop_Not64: {
5787             HReg tLo = newVRegI(env);
5788             HReg tHi = newVRegI(env);
5789             iselInt64Expr(&tHi, &tLo, env, e->Iex.Unop.arg);
5790             addInstr(env, MIPSInstr_Alu(Malu_NOR, tLo, tLo, MIPSRH_Reg(tLo)));
5791             addInstr(env, MIPSInstr_Alu(Malu_NOR, tHi, tHi, MIPSRH_Reg(tHi)));
5792 
5793             *rHi = tHi;
5794             *rLo = tLo;
5795             return;
5796          }
5797 
5798          case Iop_V128HIto64: {
5799             vassert(has_msa);
5800             HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
5801             HReg tLo = newVRegI(env);
5802             HReg tHi = newVRegI(env);
5803             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 2));
5804             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 3));
5805             *rLo = tLo;
5806             *rHi = tHi;
5807             return;
5808          }
5809 
5810          case Iop_V128to64: {
5811             vassert(has_msa);
5812             HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
5813             HReg tLo = newVRegI(env);
5814             HReg tHi = newVRegI(env);
5815             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 0));
5816             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 1));
5817             *rLo = tLo;
5818             *rHi = tHi;
5819             return;
5820          }
5821 
5822          case Iop_F32toF16x4: {
5823             vassert(has_msa);
5824             HReg v_arg = iselV128Expr(env, e->Iex.Unop.arg);
5825             HReg v_src = newVRegV(env);
5826             set_guest_MIPS_rounding_mode_MSA(env);
5827             addInstr(env, MIPSInstr_Msa3RF(MSA_FEXDO, MSA_F_WH, v_src, v_arg, v_arg));
5828             set_MIPS_rounding_default_MSA(env);
5829             HReg tLo = newVRegI(env);
5830             HReg tHi = newVRegI(env);
5831             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 0));
5832             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 1));
5833             *rLo = tLo;
5834             *rHi = tHi;
5835             return;
5836          }
5837 
5838          default:
5839             vex_printf("UNARY: No such op: ");
5840             ppIROp(e->Iex.Unop.op);
5841             vex_printf("\n");
5842             break;
5843       }
5844    }
5845 
5846    vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
5847    ppIRExpr(e);
5848    vpanic("iselInt64Expr(mips)");
5849 }
5850 
5851 /*---------------------------------------------------------*/
5852 /*--- ISEL: Floating point expressions (32 bit)         ---*/
5853 /*---------------------------------------------------------*/
5854 
5855 /* Nothing interesting here; really just wrappers for
5856    64-bit stuff. */
iselFltExpr(ISelEnv * env,IRExpr * e)5857 static HReg iselFltExpr(ISelEnv * env, IRExpr * e)
5858 {
5859     HReg r;
5860     IRType ty = typeOfIRExpr(env->type_env, e);
5861     if (ty == Ity_F32 || (ty == Ity_F64 && fp_mode64)) {
5862       r = iselFltExpr_wrk(env, e);
5863     } else {
5864       r = iselDblExpr_wrk(env, e);
5865       vassert(hregClass(r) == HRcFlt64);
5866     }
5867     return r;
5868 }
5869 
5870 /* DO NOT CALL THIS DIRECTLY */
iselFltExpr_wrk(ISelEnv * env,IRExpr * e)5871 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
5872 {
5873    IRType ty = typeOfIRExpr(env->type_env, e);
5874    vassert(ty == Ity_F32 || (ty == Ity_F64 && fp_mode64));
5875 
5876    if (e->tag == Iex_RdTmp) {
5877       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
5878    }
5879 
5880    if (e->tag == Iex_Load) {
5881       vassert(e->Iex.Load.ty == Ity_F32
5882               || (e->Iex.Load.ty == Ity_F64 && fp_mode64));
5883       HReg r_dst;
5884       MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
5885       if (e->Iex.Load.ty == Ity_F64) {
5886          r_dst = newVRegD(env);
5887          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
5888       } else {
5889          r_dst = newVRegF(env);
5890          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
5891       }
5892       return r_dst;
5893    }
5894 
5895    if (e->tag == Iex_Get) {
5896       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
5897                                         GuestStatePointer(mode64));
5898       HReg r_dst;
5899       if (e->Iex.Load.ty == Ity_F64) {
5900          r_dst = newVRegD(env);
5901          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
5902       } else {
5903          r_dst = newVRegF(env);
5904          addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
5905       }
5906       return r_dst;
5907    }
5908 
5909    if (e->tag == Iex_Unop) {
5910       switch (e->Iex.Unop.op) {
5911       case Iop_ReinterpI32asF32: {
5912          HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5913          HReg r_dst = newVRegF(env);
5914 
5915          /* Move Word to Floating Point
5916             mtc1 r_dst, valS */
5917          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, fr_src));
5918 
5919          return r_dst;
5920       }
5921       case Iop_F32toF64: {
5922          vassert(fp_mode64);
5923          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5924          HReg dst = newVRegD(env);
5925 
5926          addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
5927          return dst;
5928       }
5929       case Iop_ReinterpI64asF64: {
5930          HReg r_dst;
5931          if (mode64) {
5932             HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5933             r_dst = newVRegF(env);
5934             /* Move Doubleword to Floating Point
5935                dmtc1 r_dst, fr_src */
5936             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
5937          } else {
5938              HReg Hi, Lo;
5939              r_dst = newVRegD(env);
5940              iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
5941              r_dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
5942          }
5943          return r_dst;
5944       }
5945       case Iop_I32StoF64: {
5946          vassert(fp_mode64);
5947          HReg dst = newVRegF(env);
5948          HReg tmp = newVRegF(env);
5949          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5950 
5951          /* Move Word to Floating Point
5952             mtc1 tmp, r_src */
5953          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
5954 
5955          /* and do convert */
5956          addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
5957 
5958          return dst;
5959       }
5960       case Iop_AbsF32:
5961       case Iop_AbsF64: {
5962          Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
5963          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5964          HReg dst = newVRegF(env);
5965          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
5966          return dst;
5967       }
5968       case Iop_NegF32:
5969       case Iop_NegF64: {
5970          Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
5971          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5972          HReg dst = newVRegF(env);
5973          addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
5974          return dst;
5975       }
5976       case Iop_RoundF64toF64_ZERO: {
5977          vassert(mode64);
5978          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5979          HReg dst = newVRegF(env);
5980          addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, dst, src));
5981          return dst;
5982       }
5983       case Iop_RoundF64toF64_NEAREST: {
5984          vassert(mode64);
5985          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5986          HReg dst = newVRegF(env);
5987          addInstr(env, MIPSInstr_FpConvert(Mfp_ROUNDLD, dst, src));
5988          return dst;
5989       }
5990       case Iop_RoundF64toF64_NegINF: {
5991          vassert(mode64);
5992          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5993          HReg dst = newVRegF(env);
5994          addInstr(env, MIPSInstr_FpConvert(Mfp_FLOORLD, dst, src));
5995          return dst;
5996       }
5997       case Iop_RoundF64toF64_PosINF: {
5998          vassert(mode64);
5999          HReg src = iselFltExpr(env, e->Iex.Unop.arg);
6000          HReg dst = newVRegF(env);
6001          addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, dst, src));
6002          return dst;
6003       }
6004 
6005       default:
6006          break;
6007       }
6008    }
6009 
6010    if (e->tag == Iex_Triop) {
6011       switch (e->Iex.Triop.details->op) {
6012          case Iop_DivF32:
6013          case Iop_DivF64:
6014          case Iop_MulF32:
6015          case Iop_MulF64:
6016          case Iop_AddF32:
6017          case Iop_AddF64:
6018          case Iop_SubF32:
6019          case Iop_SubF64: {
6020             MIPSFpOp op = 0;
6021             HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
6022             HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
6023             HReg dst = newVRegF(env);
6024             switch (e->Iex.Triop.details->op) {
6025                case Iop_DivF32:
6026                   op = Mfp_DIVS;
6027                   break;
6028                case Iop_DivF64:
6029                   vassert(fp_mode64);
6030                   op = Mfp_DIVD;
6031                   break;
6032                case Iop_MulF32:
6033                   op = Mfp_MULS;
6034                   break;
6035                case Iop_MulF64:
6036                   vassert(fp_mode64);
6037                   op = Mfp_MULD;
6038                   break;
6039                case Iop_AddF32:
6040                   op = Mfp_ADDS;
6041                   break;
6042                case Iop_AddF64:
6043                   vassert(fp_mode64);
6044                   op = Mfp_ADDD;
6045                   break;
6046                case Iop_SubF32:
6047                   op = Mfp_SUBS;
6048                   break;
6049                case Iop_SubF64:
6050                   vassert(fp_mode64);
6051                   op = Mfp_SUBD;
6052                   break;
6053                default:
6054                   vassert(0);
6055             }
6056             set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
6057             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
6058             set_MIPS_rounding_default(env);
6059             return dst;
6060          }
6061          case Iop_ScaleF64: {
6062             HReg src1   = iselFltExpr(env, e->Iex.Triop.details->arg2);
6063             HReg src2   = iselFltExpr(env, e->Iex.Triop.details->arg3);
6064             HReg v_help = newVRegV(env);
6065             HReg dst    = newVRegF(env);
6066             vassert(has_msa);
6067             set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
6068             addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_S, MSA_F_DW, v_help, src2));
6069             addInstr(env, MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW, dst, src1, v_help));
6070             set_MIPS_rounding_default_MSA(env);
6071 
6072             return dst;
6073          }
6074          default:
6075             break;
6076       }
6077    }
6078 
6079    if (e->tag == Iex_Binop) {
6080       switch (e->Iex.Binop.op) {
6081          case Iop_F64toF32: {
6082             HReg valD;
6083             if (mode64)
6084                valD = iselFltExpr(env, e->Iex.Binop.arg2);
6085             else
6086                valD = iselDblExpr(env, e->Iex.Binop.arg2);
6087             HReg valS = newVRegF(env);
6088 
6089             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6090             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
6091             set_MIPS_rounding_default(env);
6092             return valS;
6093          }
6094 
6095          case Iop_RoundF32toInt: {
6096                HReg valS = newVRegF(env);
6097                HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
6098 
6099                set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6100 #if (__mips_isa_rev >= 6)
6101                addInstr(env, MIPSInstr_FpConvert(Mfp_RINTS, valS, valF));
6102 #else
6103                addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
6104                addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, valS, valS));
6105 #endif
6106                set_MIPS_rounding_default(env);
6107                return valS;
6108             }
6109 
6110          case Iop_RoundF64toInt: {
6111             HReg valS = newVRegF(env);
6112             HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
6113 
6114             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6115 #if (__mips_isa_rev >= 6)
6116             addInstr(env, MIPSInstr_FpConvert(Mfp_RINTD, valS, valF));
6117 #else
6118             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, valS, valF));
6119             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, valS, valS));
6120 
6121 #endif
6122             set_MIPS_rounding_default(env);
6123             return valS;
6124          }
6125 
6126          case Iop_I32StoF32: {
6127             HReg r_dst = newVRegF(env);
6128             HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6129             HReg tmp = newVRegF(env);
6130 
6131             /* Move Word to Floating Point
6132                mtc1 tmp, fr_src */
6133             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, fr_src));
6134 
6135             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6136             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
6137             set_MIPS_rounding_default(env);
6138 
6139             return r_dst;
6140          }
6141 
6142          case Iop_I64StoF64: {
6143             HReg r_dst = newVRegF(env);
6144             MIPSAMode *am_addr;
6145             HReg tmp, fr_src;
6146             if (mode64) {
6147                tmp = newVRegF(env);
6148                fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6149                /* Move SP down 8 bytes */
6150                sub_from_sp(env, 8);
6151                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6152 
6153                /* store as I64 */
6154                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6155 
6156                /* load as Ity_F64 */
6157                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6158 
6159                /* Reset SP */
6160                add_to_sp(env, 8);
6161             } else {
6162                HReg Hi, Lo;
6163                tmp = newVRegD(env);
6164                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6165                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
6166             }
6167 
6168             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6169             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6170             set_MIPS_rounding_default(env);
6171 
6172             return r_dst;
6173          }
6174 
6175          case Iop_I64StoF32: {
6176             HReg r_dst = newVRegF(env);
6177             MIPSAMode *am_addr;
6178             HReg fr_src, tmp;
6179             if (mode64) {
6180                tmp = newVRegF(env);
6181                fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6182                /* Move SP down 8 bytes */
6183                sub_from_sp(env, 8);
6184                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6185 
6186                /* store as I64 */
6187                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6188 
6189                /* load as Ity_F64 */
6190                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6191 
6192                /* Reset SP */
6193                add_to_sp(env, 8);
6194             } else {
6195                HReg Hi, Lo;
6196                tmp = newVRegD(env);
6197                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6198                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
6199             }
6200 
6201             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6202             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSL, r_dst, tmp));
6203             set_MIPS_rounding_default(env);
6204 
6205             return r_dst;
6206          }
6207 
6208          case Iop_SqrtF32:
6209          case Iop_SqrtF64: {
6210             Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
6211             HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
6212             HReg dst = newVRegF(env);
6213             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6214             addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
6215                                             src));
6216             set_MIPS_rounding_default(env);
6217             return dst;
6218          }
6219 
6220          case Iop_I64UtoF64: {
6221             vassert(mode64);
6222             HReg r_dst = newVRegF(env);
6223             HReg tmp = newVRegV(env);
6224             HReg r_src;
6225             vassert(has_msa);
6226             r_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6227             set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
6228             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src, tmp));
6229             HReg r_srch = newVRegI(env);
6230             addInstr(env, MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_DW, tmp, tmp));
6231             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srch, MSA_DFN_D | 0));
6232             sub_from_sp(env, 8);
6233             MIPSAMode *am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6234 
6235             /* store as I64 */
6236             addInstr(env, MIPSInstr_Store(8, am_addr, r_srch, mode64));
6237 
6238             /* load as Ity_F64 */
6239             addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
6240 
6241             /* Reset SP */
6242             add_to_sp(env, 8);
6243             set_MIPS_rounding_default_MSA(env);
6244             return r_dst;
6245           }
6246 
6247 #if (__mips_isa_rev >= 6)
6248          case Iop_MaxNumF32: {
6249             HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6250             HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6251             HReg dst = newVRegF(env);
6252             addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXS, dst,
6253                                             src1, src2));
6254             return dst;
6255          }
6256 
6257          case Iop_MaxNumF64: {
6258             HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6259             HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6260             HReg dst = newVRegF(env);
6261             addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXD, dst,
6262                                             src1, src2));
6263             return dst;
6264          }
6265 
6266          case Iop_MinNumF32: {
6267             HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6268             HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6269             HReg dst = newVRegF(env);
6270             addInstr(env, MIPSInstr_FpMinMax(Mfp_MINS, dst,
6271                                             src1, src2));
6272             return dst;
6273          }
6274 
6275          case Iop_MinNumF64: {
6276             HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6277             HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6278             HReg dst = newVRegF(env);
6279             addInstr(env, MIPSInstr_FpMinMax(Mfp_MIND, dst,
6280                                             src1, src2));
6281             return dst;
6282          }
6283 #endif
6284          default:
6285             break;
6286       }
6287    }
6288 
6289    if (e->tag == Iex_Qop) {
6290       switch (e->Iex.Qop.details->op) {
6291          case Iop_MAddF32:
6292          case Iop_MAddF64:
6293          case Iop_MSubF32:
6294          case Iop_MSubF64: {
6295             Int op = 0;
6296 #if (__mips_isa_rev < 6)
6297             MSADFFlx type = 0;
6298 #endif
6299             switch (e->Iex.Qop.details->op) {
6300 #if (__mips_isa_rev >= 6)
6301               case Iop_MAddF32:
6302                   op = Mfp_MADDS;
6303                   break;
6304                case Iop_MAddF64:
6305                   op = Mfp_MADDD;
6306                   break;
6307                case Iop_MSubF32:
6308                   op = Mfp_MSUBS;
6309                   break;
6310                case Iop_MSubF64:
6311                   op = Mfp_MSUBD;
6312                   break;
6313 #else
6314                case Iop_MAddF32:
6315                   op = has_msa ? MSA_FMADD : Mfp_MADDS;
6316                   type = MSA_F_WH;
6317                   break;
6318                case Iop_MAddF64:
6319                   op = has_msa ? MSA_FMADD : Mfp_MADDD;
6320                   type = MSA_F_DW;
6321                   break;
6322                case Iop_MSubF32:
6323                   op = has_msa ? MSA_FMSUB : Mfp_MSUBS;
6324                   type = MSA_F_WH;
6325                   break;
6326                case Iop_MSubF64:
6327                   op = has_msa ? MSA_FMSUB : Mfp_MSUBD;
6328                   type = MSA_F_DW;
6329                   break;
6330 #endif
6331                default:
6332                   vassert(0);
6333             }
6334 
6335             HReg dst = newVRegF(env);
6336             HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
6337             HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
6338             HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
6339 #if (__mips_isa_rev >= 6)
6340             set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6341             addInstr(env, MIPSInstr_FpTernary(op, dst,
6342                                               src3, src1, src2));
6343             set_MIPS_rounding_default(env);
6344 #else
6345             if (has_msa) {
6346                addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, src3, dst, 0));
6347                set_MIPS_rounding_mode_MSA(env, e->Iex.Qop.details->arg1);
6348                addInstr(env, MIPSInstr_Msa3RF(op, type, dst, src1, src2));
6349                set_MIPS_rounding_default_MSA(env);
6350             } else {
6351                set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6352                addInstr(env, MIPSInstr_FpTernary(op, dst,
6353                                                  src1, src2, src3));
6354                set_MIPS_rounding_default(env);
6355             }
6356 #endif
6357             return dst;
6358          }
6359 
6360          default:
6361          break;
6362       }
6363    }
6364 
6365    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
6366       /* This is quite subtle.  The only way to do the relevant
6367          truncation is to do a single-precision store and then a
6368          double precision load to get it back into a register.  The
6369          problem is, if the data is then written to memory a second
6370          time, as in
6371 
6372          STbe(...) = TruncF64asF32(...)
6373 
6374          then will the second truncation further alter the value?  The
6375          answer is no: flds (as generated here) followed by fsts
6376          (generated for the STbe) is the identity function on 32-bit
6377          floats, so we are safe.
6378 
6379          Another upshot of this is that if iselStmt can see the
6380          entirety of
6381 
6382          STbe(...) = TruncF64asF32(arg)
6383 
6384          then it can short circuit having to deal with TruncF64asF32
6385          individually; instead just compute arg into a 64-bit FP
6386          register and do 'fsts' (since that itself does the
6387          truncation).
6388 
6389          We generate pretty poor code here (should be ok both for
6390          32-bit and 64-bit mode); but it is expected that for the most
6391          part the latter optimisation will apply and hence this code
6392          will not often be used.
6393        */
6394       HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
6395       HReg fdst = newVRegF(env);
6396       MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
6397 
6398       sub_from_sp(env, 16);
6399       /* store as F32, hence truncating */
6400       addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
6401       /* and reload.  Good huh?! (sigh) */
6402       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
6403       add_to_sp(env, 16);
6404       return fdst;
6405    }
6406 
6407    /* --------- ITE --------- */
6408    if (e->tag == Iex_ITE) {
6409       vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
6410       HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
6411       HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
6412       HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
6413       HReg r_dst = newVRegF(env);
6414 #if (__mips_isa_rev >= 6)
6415          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, r_cond));
6416          addInstr(env, MIPSInstr_MoveCond(MFpSeld, r_dst, r0, r1));
6417 #else
6418       addInstr(env, MIPSInstr_FpUnary((ty == Ity_F64) ? Mfp_MOVD : Mfp_MOVS,
6419                                       r_dst, r0));
6420       addInstr(env, MIPSInstr_MoveCond((ty == Ity_F64) ? MFpMoveCond_movnd :
6421                                                          MFpMoveCond_movns,
6422                                        r_dst, r1, r_cond));
6423 #endif
6424       return r_dst;
6425    }
6426 
6427    vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
6428    ppIRExpr(e);
6429    vpanic("iselFltExpr_wrk(mips)");
6430 }
6431 
iselDblExpr(ISelEnv * env,IRExpr * e)6432 static HReg iselDblExpr(ISelEnv * env, IRExpr * e)
6433 {
6434    HReg r = iselDblExpr_wrk(env, e);
6435    vassert(hregClass(r) == HRcFlt64);
6436    vassert(hregIsVirtual(r));
6437    return r;
6438 }
6439 
6440 /* DO NOT CALL THIS DIRECTLY */
iselDblExpr_wrk(ISelEnv * env,IRExpr * e)6441 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
6442 {
6443    IRType ty = typeOfIRExpr(env->type_env, e);
6444    vassert(e);
6445    vassert(ty == Ity_F64);
6446 
6447    if (e->tag == Iex_RdTmp) {
6448       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
6449    }
6450 
6451    /* --------- LOAD --------- */
6452    if (e->tag == Iex_Load) {
6453       HReg r_dst = newVRegD(env);
6454       MIPSAMode *am_addr;
6455       vassert(e->Iex.Load.ty == Ity_F64);
6456       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
6457       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
6458       return r_dst;
6459    }
6460 
6461    /* --------- GET --------- */
6462    if (e->tag == Iex_Get) {
6463 
6464       HReg r_dst = newVRegD(env);
6465       MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
6466                                         GuestStatePointer(mode64));
6467       addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
6468       return r_dst;
6469    }
6470 
6471    if (e->tag == Iex_Unop) {
6472       MIPSFpOp fpop = Mfp_INVALID;
6473       switch (e->Iex.Unop.op) {
6474          case Iop_NegF64:
6475             fpop = Mfp_NEGD;
6476             break;
6477          case Iop_AbsF64:
6478             fpop = Mfp_ABSD;
6479             break;
6480          case Iop_F32toF64: {
6481             vassert(!mode64);
6482             HReg src = iselFltExpr(env, e->Iex.Unop.arg);
6483             HReg dst = newVRegD(env);
6484 
6485             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
6486             return dst;
6487          }
6488          case Iop_ReinterpI64asF64: {
6489             HReg Hi, Lo;
6490             HReg dst = newVRegD(env);
6491 
6492             iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
6493 
6494             dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
6495             return dst;
6496          }
6497          case Iop_I32StoF64: {
6498             vassert(!mode64);
6499             HReg dst = newVRegD(env);
6500             HReg tmp = newVRegF(env);
6501             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
6502 
6503             /* Move Word to Floating Point
6504                mtc1 tmp, r_src */
6505             addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
6506 
6507             /* and do convert */
6508             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
6509 
6510             return dst;
6511          }
6512          default:
6513             break;
6514       }
6515 
6516       if (fpop != Mfp_INVALID) {
6517          HReg src = iselDblExpr(env, e->Iex.Unop.arg);
6518          HReg dst = newVRegD(env);
6519          addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
6520          return dst;
6521       }
6522    }
6523 
6524    if (e->tag == Iex_Binop) {
6525       switch (e->Iex.Binop.op) {
6526          case Iop_RoundF64toInt: {
6527             HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
6528             HReg dst = newVRegD(env);
6529 
6530             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6531 #if (__mips_isa_rev >= 6)
6532             addInstr(env, MIPSInstr_FpConvert(Mfp_RINTD, dst, src));
6533 #else
6534             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, dst, src));
6535             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, dst, dst));
6536 
6537 #endif
6538             set_MIPS_rounding_default(env);
6539 
6540             return dst;
6541          }
6542 
6543          case Iop_SqrtF64: {
6544             HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
6545             HReg dst = newVRegD(env);
6546             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6547             addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
6548             set_MIPS_rounding_default(env);
6549             return dst;
6550          }
6551 
6552          case Iop_I64StoF64: {
6553             HReg r_dst = newVRegD(env);
6554             MIPSAMode *am_addr;
6555             HReg tmp, fr_src;
6556             if (mode64) {
6557                tmp = newVRegD(env);
6558                fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
6559                /* Move SP down 8 bytes */
6560                sub_from_sp(env, 8);
6561                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6562 
6563                /* store as I64 */
6564                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6565 
6566                /* load as Ity_F64 */
6567                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6568 
6569                /* Reset SP */
6570                add_to_sp(env, 8);
6571             } else {
6572                HReg Hi, Lo;
6573                tmp = newVRegD(env);
6574                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6575                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
6576             }
6577 
6578             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6579             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6580             set_MIPS_rounding_default(env);
6581 
6582             return r_dst;
6583          }
6584 
6585          case Iop_I64UtoF64: {
6586             HReg r_dst;
6587             HReg tmp = newVRegV(env);
6588             HReg r_src2h, r_src2l;
6589             vassert(has_msa);
6590             iselInt64Expr(&r_src2h, &r_src2l, env, e->Iex.Binop.arg2);
6591             set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
6592             addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_src2l, tmp));
6593             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2h, tmp, MSA_DFN_W | 1));
6594             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2l, tmp, MSA_DFN_W | 2));
6595             addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2h, tmp, MSA_DFN_W | 3));
6596             HReg r_srchh = newVRegI(env);
6597             HReg r_srchl = newVRegI(env);
6598             addInstr(env, MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_DW, tmp, tmp));
6599             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srchl, MSA_DFN_W | 0));
6600             addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srchh, MSA_DFN_W | 1));
6601             r_dst = mk_LoadRR32toFPR(env, r_srchh, r_srchl);
6602             set_MIPS_rounding_default_MSA(env);
6603             return r_dst;
6604           }
6605 #if (__mips_isa_rev >= 6)
6606          case Iop_MaxNumF64: {
6607             HReg src1 = iselDblExpr(env, e->Iex.Binop.arg1);
6608             HReg src2 = iselDblExpr(env, e->Iex.Binop.arg2);
6609             HReg dst = newVRegD(env);
6610             addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXD, dst,
6611                                             src1, src2));
6612             return dst;
6613          }
6614 
6615          case Iop_MinNumF64: {
6616             HReg src1 = iselDblExpr(env, e->Iex.Binop.arg1);
6617             HReg src2 = iselDblExpr(env, e->Iex.Binop.arg2);
6618             HReg dst = newVRegD(env);
6619             addInstr(env, MIPSInstr_FpMinMax(Mfp_MIND, dst,
6620                                             src1, src2));
6621             return dst;
6622          }
6623 #endif
6624 
6625          default:
6626             break;
6627 
6628       }
6629    }
6630 
6631    if (e->tag == Iex_Triop) {
6632       switch (e->Iex.Triop.details->op) {
6633          case Iop_DivF64:
6634          case Iop_DivF32:
6635          case Iop_MulF64:
6636          case Iop_AddF64:
6637          case Iop_SubF64: {
6638             MIPSFpOp op = 0;
6639             HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
6640             HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
6641             HReg dst = newVRegD(env);
6642             switch (e->Iex.Triop.details->op) {
6643                case Iop_DivF64:
6644                   op = Mfp_DIVD;
6645                   break;
6646                case Iop_DivF32:
6647                   op = Mfp_DIVS;
6648                   break;
6649                case Iop_MulF64:
6650                   op = Mfp_MULD;
6651                   break;
6652                case Iop_AddF64:
6653                   op = Mfp_ADDD;
6654                   break;
6655                case Iop_SubF64:
6656                   op = Mfp_SUBD;
6657                   break;
6658                default:
6659                   vassert(0);
6660             }
6661             set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
6662             addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
6663             set_MIPS_rounding_default(env);
6664             return dst;
6665          }
6666 
6667          case Iop_ScaleF64: {
6668             HReg src1   = iselDblExpr(env, e->Iex.Triop.details->arg2);
6669             HReg src2   = iselDblExpr(env, e->Iex.Triop.details->arg3);
6670             HReg v_help = newVRegV(env);
6671             HReg dst    = newVRegD(env);
6672             vassert(has_msa);
6673             set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
6674             addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_S, MSA_F_DW, v_help, src2));
6675             addInstr(env, MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW, dst, src1, v_help));
6676             set_MIPS_rounding_default_MSA(env);
6677             return dst;
6678          }
6679          default:
6680             break;
6681       }
6682    }
6683 
6684    if (e->tag == Iex_Qop) {
6685       switch (e->Iex.Qop.details->op) {
6686          case Iop_MAddF64:
6687          case Iop_MSubF64: {
6688             MSA3RFOp op = 0;
6689             switch (e->Iex.Qop.details->op) {
6690 #if (__mips_isa_rev >= 6)
6691               case Iop_MAddF64:
6692                   op = Mfp_MADDD;
6693                   break;
6694                case Iop_MSubF64:
6695                   op = Mfp_MSUBD;
6696                   break;
6697 #else
6698                case Iop_MAddF64:
6699                   op = MSA_FMADD;
6700                   break;
6701                case Iop_MSubF64:
6702                   op = MSA_FMSUB;
6703                   break;
6704 #endif
6705                default:
6706                   vassert(0);
6707             }
6708             HReg dst = newVRegD(env);
6709             HReg src1 = iselDblExpr(env, e->Iex.Qop.details->arg2);
6710             HReg src2 = iselDblExpr(env, e->Iex.Qop.details->arg3);
6711             HReg src3 = iselDblExpr(env, e->Iex.Qop.details->arg4);
6712 #if (__mips_isa_rev >= 6)
6713             set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6714             addInstr(env, MIPSInstr_FpTernary(op, dst,
6715                                               src3, src1, src2));
6716             set_MIPS_rounding_default(env);
6717 #else
6718             vassert(has_msa);
6719             addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, src3, dst, 0));
6720             set_MIPS_rounding_mode_MSA(env, e->Iex.Qop.details->arg1);
6721             addInstr(env, MIPSInstr_Msa3RF(op, MSA_F_DW, dst, src1, src2));
6722             set_MIPS_rounding_default_MSA(env);
6723 #endif
6724             return dst;
6725          }
6726          case Iop_I64StoF64: {
6727             HReg r_dst = newVRegD(env);
6728             MIPSAMode *am_addr;
6729             HReg tmp, fr_src;
6730             if (mode64) {
6731                tmp = newVRegF(env);
6732                fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6733                /* Move SP down 8 bytes */
6734                sub_from_sp(env, 8);
6735                am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6736 
6737                /* store as I64 */
6738                addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6739 
6740                /* load as Ity_F64 */
6741                addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6742 
6743                /* Reset SP */
6744                add_to_sp(env, 8);
6745             } else {
6746                HReg Hi, Lo;
6747                tmp = newVRegD(env);
6748                iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6749                tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
6750             }
6751 
6752             set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6753             addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6754             set_MIPS_rounding_default(env);
6755 
6756             return r_dst;
6757          }
6758 
6759          default:
6760          break;
6761       }
6762    }
6763 
6764    /* --------- ITE --------- */
6765    if (e->tag == Iex_ITE) {
6766       if (ty == Ity_F64
6767           && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
6768          HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse);
6769          HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue);
6770          HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
6771          HReg r_dst = newVRegD(env);
6772 #if (__mips_isa_rev >= 6)
6773          addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, r_cond));
6774          addInstr(env, MIPSInstr_MoveCond(MFpSeld, r_dst, r0, r1));
6775 #else
6776          addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
6777          addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
6778                                             r_cond));
6779 #endif
6780          return r_dst;
6781       }
6782    }
6783 
6784    vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
6785    ppIRExpr(e);
6786    vpanic("iselDblExpr_wrk(mips)");
6787 }
6788 
6789 /*---------------------------------------------------------*/
6790 /*--- ISEL: Statements                                  ---*/
6791 /*---------------------------------------------------------*/
6792 
iselStmt(ISelEnv * env,IRStmt * stmt)6793 static void iselStmt(ISelEnv * env, IRStmt * stmt)
6794 {
6795    if (vex_traceflags & VEX_TRACE_VCODE) {
6796       vex_printf("\n-- ");
6797 
6798       ppIRStmt(stmt);
6799       vex_printf("\n");
6800    }
6801 
6802    switch (stmt->tag) {
6803       /* --------- STORE --------- */
6804       case Ist_Store: {
6805          MIPSAMode *am_addr;
6806          IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
6807 
6808          if (tyd == Ity_V128) {
6809             vassert(has_msa);
6810             HReg res = iselV128Expr(env, stmt->Ist.Store.data);
6811             HReg addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
6812             addInstr(env, MIPSInstr_MsaMi10(MSA_ST, 0, addr, res, MSA_B));
6813             return;
6814          }
6815 
6816          /*constructs addressing mode from address provided */
6817          am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
6818 
6819          if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
6820              (mode64 && (tyd == Ity_I64))) {
6821             HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
6822             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
6823                      am_addr, r_src, mode64));
6824             return;
6825          }
6826          if (!mode64 && (tyd == Ity_I64)) {
6827             HReg vHi, vLo;
6828             HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
6829 
6830             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
6831 
6832             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6833                           MIPSAMode_IR(0, r_addr), vHi, mode64));
6834             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6835                           MIPSAMode_IR(4, r_addr), vLo, mode64));
6836             return;
6837          }
6838          if (tyd == Ity_F32) {
6839             HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
6840             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
6841                                            am_addr));
6842             return;
6843          }
6844          if (tyd == Ity_F64 && mode64) {
6845             HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
6846             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6847                                            am_addr));
6848             return;
6849          }
6850          if (!mode64 && (tyd == Ity_F64)) {
6851             HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
6852             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6853                                            am_addr));
6854             return;
6855          }
6856 
6857          break;
6858       }
6859 
6860       /* --------- PUT --------- */
6861       case Ist_Put: {
6862          IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
6863 
6864          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
6865              (ty == Ity_I64 && mode64)) {
6866             HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
6867             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6868                                               GuestStatePointer(mode64));
6869             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
6870                                           am_addr, r_src, mode64));
6871             return;
6872          }
6873 
6874          if (ty == Ity_I64 && !mode64) {
6875             HReg vHi, vLo;
6876             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6877                                               GuestStatePointer(mode64));
6878             MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
6879                                                GuestStatePointer(mode64));
6880             iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
6881             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6882                                           am_addr, vLo, mode64));
6883             addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6884                                           am_addr4, vHi, mode64));
6885             return;
6886 
6887          }
6888 
6889          if (ty == Ity_F32) {
6890             HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
6891             MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6892                                               GuestStatePointer(mode64));
6893             addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
6894                                            am_addr));
6895             return;
6896          }
6897 
6898          if (ty == Ity_F64) {
6899             if (mode64) {
6900               HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
6901               MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6902                                                 GuestStatePointer(mode64));
6903               addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6904                                              am_addr));
6905             } else {
6906               HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data);
6907               MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6908                                                 GuestStatePointer(mode64));
6909               addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6910                                              am_addr));
6911             }
6912             return;
6913          }
6914          if (ty == Ity_V128) {
6915             vassert(has_msa);
6916             HReg v_src = iselV128Expr(env, stmt->Ist.Put.data);
6917 #if defined(_MIPSEB)
6918             HReg r_addr = newVRegI(env);
6919             addInstr(env, MIPSInstr_Alu(mode64 ? Malu_DADD : Malu_ADD, r_addr, GuestStatePointer(mode64),
6920                                         MIPSRH_Imm(False, stmt->Ist.Put.offset)));
6921             addInstr(env, MIPSInstr_MsaMi10(MSA_ST, 0, r_addr, v_src, MSA_B));
6922 #else
6923             vassert(!(stmt->Ist.Put.offset & 7));
6924             addInstr(env, MIPSInstr_MsaMi10(MSA_ST, stmt->Ist.Put.offset >> 3,
6925                                             GuestStatePointer(mode64), v_src, MSA_D));
6926 #endif
6927             return;
6928          }
6929          break;
6930       }
6931 
6932       /* --------- TMP --------- */
6933       case Ist_WrTmp: {
6934          IRTemp tmp = stmt->Ist.WrTmp.tmp;
6935          IRType ty = typeOfIRTemp(env->type_env, tmp);
6936 
6937          if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
6938             HReg r_dst = lookupIRTemp(env, tmp);
6939             HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
6940             addInstr(env, mk_iMOVds_RR(r_dst, r_src));
6941             return;
6942          }
6943 
6944          if (ty == Ity_I64) {
6945             if (mode64) {
6946                HReg r_dst = lookupIRTemp(env, tmp);
6947                HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
6948                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
6949                return;
6950             } else {
6951                HReg rHi, rLo, dstHi, dstLo;
6952                iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
6953                lookupIRTemp64(&dstHi, &dstLo, env, tmp);
6954                addInstr(env, mk_iMOVds_RR(dstHi, rHi));
6955                addInstr(env, mk_iMOVds_RR(dstLo, rLo));
6956                return;
6957             }
6958          }
6959 
6960          if (mode64 && ty == Ity_I128) {
6961             HReg rHi, rLo, dstHi, dstLo;
6962             iselInt128Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
6963             lookupIRTempPair(&dstHi, &dstLo, env, tmp);
6964             addInstr(env, mk_iMOVds_RR(dstHi, rHi));
6965             addInstr(env, mk_iMOVds_RR(dstLo, rLo));
6966             return;
6967          }
6968 
6969          if (ty == Ity_F32) {
6970             HReg fr_dst = lookupIRTemp(env, tmp);
6971             HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
6972             addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
6973             return;
6974          }
6975 
6976          if (ty == Ity_F64) {
6977             if (mode64) {
6978                HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
6979                HReg dst = lookupIRTemp(env, tmp);
6980                addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
6981                return;
6982             } else {
6983                HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
6984                HReg dst = lookupIRTemp(env, tmp);
6985                addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
6986                return;
6987             }
6988          }
6989 
6990          if (ty == Ity_V128) {
6991             vassert(has_msa);
6992             HReg v_dst = lookupIRTemp(env, tmp);
6993             HReg v_src = iselV128Expr(env, stmt->Ist.WrTmp.data);
6994             addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, v_src, v_dst, 0));
6995             return;
6996           }
6997          break;
6998       }
6999 
7000       /* --------- Call to DIRTY helper --------- */
7001       case Ist_Dirty: {
7002          IRDirty *d = stmt->Ist.Dirty.details;
7003 
7004          /* Figure out the return type, if any. */
7005          IRType retty = Ity_INVALID;
7006          if (d->tmp != IRTemp_INVALID)
7007             retty = typeOfIRTemp(env->type_env, d->tmp);
7008 
7009          /* Throw out any return types we don't know about. */
7010          Bool retty_ok = False;
7011          switch (retty) {
7012             case Ity_INVALID: /* Function doesn't return anything. */
7013             case Ity_V128:
7014             case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
7015                retty_ok = True; break;
7016             default:
7017                break;
7018          }
7019 
7020          if (!retty_ok)
7021             break; /* will go to stmt_fail: */
7022 
7023          /* Marshal args, do the call, clear stack, set the return value
7024             to 0x555..555 if this is a conditional call that returns a
7025             value and the call is skipped. */
7026          UInt   addToSp = 0;
7027          RetLoc rloc    = mk_RetLoc_INVALID();
7028          doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args );
7029          vassert(is_sane_RetLoc(rloc));
7030 
7031          /* Now figure out what to do with the returned value, if any. */
7032          switch (retty) {
7033             case Ity_INVALID: {
7034                /* No return value.  Nothing to do. */
7035                vassert(d->tmp == IRTemp_INVALID);
7036                vassert(rloc.pri == RLPri_None);
7037                vassert(addToSp == 0);
7038                return;
7039             }
7040             case Ity_I32: case Ity_I16: case Ity_I8: {
7041                /* The returned value is in $v0.  Park it in the register
7042                   associated with tmp. */
7043                HReg r_dst = lookupIRTemp(env, d->tmp);
7044                addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_dst,
7045                                             hregMIPS_GPR2(mode64),
7046                                             MIPSRH_Imm(False, 0)));
7047                vassert(rloc.pri == RLPri_Int);
7048                vassert(addToSp == 0);
7049                return;
7050             }
7051             case Ity_I64: {
7052                if (mode64) {
7053                   /* The returned value is in $v0.  Park it in the register
7054                      associated with tmp. */
7055                   HReg r_dst = lookupIRTemp(env, d->tmp);
7056                   addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
7057                   vassert(rloc.pri == RLPri_Int);
7058                   vassert(addToSp == 0);
7059                   return;
7060                } else {
7061                   HReg rHi = newVRegI(env);
7062                   HReg rLo = newVRegI(env);
7063                   HReg dstHi, dstLo;
7064                   addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64)));
7065                   addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64)));
7066                   lookupIRTemp64(&dstHi, &dstLo, env, d->tmp);
7067                   addInstr(env, mk_iMOVds_RR(dstHi, rHi));
7068                   addInstr(env, mk_iMOVds_RR(dstLo, rLo));
7069                   return;
7070                }
7071             }
7072             case Ity_V128: {
7073                vassert(has_msa);
7074                vassert(rloc.pri == RLPri_V128SpRel);
7075                vassert((rloc.spOff < 512) && (rloc.spOff > -512));
7076                vassert(addToSp >= 16);
7077                HReg       dst = lookupIRTemp(env, d->tmp);
7078                addInstr(env, MIPSInstr_MsaMi10(MSA_LD, rloc.spOff, StackPointer(mode64), dst, MSA_B));
7079                add_to_sp(env, addToSp);
7080                return;
7081 
7082             }
7083             default:
7084                /*NOTREACHED*/
7085                vassert(0);
7086          }
7087       }
7088 
7089       /* --------- Load Linked or Store Conditional --------- */
7090       case Ist_LLSC: {
7091          /* Temporary solution; this need to be rewritten again for MIPS.
7092             On MIPS you can not read from address that is locked with LL
7093             before SC. If you read from address that is locked than SC will
7094             fall. */
7095          IRTemp res = stmt->Ist.LLSC.result;
7096          IRType tyRes = typeOfIRTemp(env->type_env, res);
7097          IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
7098 
7099          if (!mode64 && (tyAddr != Ity_I32))
7100             goto stmt_fail;
7101 
7102          if (stmt->Ist.LLSC.storedata == NULL) {
7103             /* LL */
7104             MIPSAMode *r_addr;
7105             /* constructs addressing mode from address provided */
7106             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
7107 
7108             HReg r_dst = lookupIRTemp(env, res);
7109             if (tyRes == Ity_I32) {
7110                addInstr(env, MIPSInstr_LoadL(4, r_dst, r_addr, mode64));
7111                return;
7112             } else if (tyRes == Ity_I64 && mode64) {
7113                addInstr(env, MIPSInstr_LoadL(8, r_dst, r_addr, mode64));
7114                return;
7115             }
7116          } else {
7117             /* SC */
7118             MIPSAMode *r_addr;
7119             r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
7120             HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
7121             HReg r_dst = lookupIRTemp(env, res);
7122             IRType tyData = typeOfIRExpr(env->type_env,
7123                                          stmt->Ist.LLSC.storedata);
7124 
7125             if (tyData == Ity_I32) {
7126                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
7127                addInstr(env, MIPSInstr_StoreC(4, r_addr, r_dst, mode64));
7128                return;
7129             } else if (tyData == Ity_I64 && mode64) {
7130                addInstr(env, mk_iMOVds_RR(r_dst, r_src));
7131                addInstr(env, MIPSInstr_StoreC(8, r_addr, r_dst, mode64));
7132                return;
7133             }
7134          }
7135          goto stmt_fail;
7136        /* NOTREACHED */}
7137 
7138    case Ist_CAS:
7139       if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
7140          IRCAS *cas = stmt->Ist.CAS.details;
7141          HReg old   = lookupIRTemp(env, cas->oldLo);
7142          HReg addr  = iselWordExpr_R(env, cas->addr);
7143          HReg expd  = iselWordExpr_R(env, cas->expdLo);
7144          HReg data  = iselWordExpr_R(env, cas->dataLo);
7145          if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I64) {
7146             addInstr(env, MIPSInstr_Cas(8, old, addr, expd, data, mode64));
7147          } else if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
7148             addInstr(env, MIPSInstr_Cas(4, old, addr, expd, data, mode64));
7149          }
7150       }
7151       return;
7152 
7153    /* --------- INSTR MARK --------- */
7154    /* Doesn't generate any executable code ... */
7155    case Ist_IMark:
7156       return;
7157 
7158    /* --------- ABI HINT --------- */
7159    /* These have no meaning (denotation in the IR) and so we ignore
7160       them ... if any actually made it this far. */
7161    case Ist_AbiHint:
7162       return;
7163 
7164    /* --------- NO-OP --------- */
7165    /* Fairly self-explanatory, wouldn't you say? */
7166    case Ist_NoOp:
7167       return;
7168 
7169    /* --------- EXIT --------- */
7170    case Ist_Exit: {
7171       IRConst* dst = stmt->Ist.Exit.dst;
7172       if (!mode64 && dst->tag != Ico_U32)
7173          vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
7174       if (mode64 && dst->tag != Ico_U64)
7175          vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
7176 
7177       MIPSCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
7178       MIPSAMode*   amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
7179                                       GuestStatePointer(mode64));
7180 
7181       /* Case: boring transfer to known address */
7182       if (stmt->Ist.Exit.jk == Ijk_Boring
7183           || stmt->Ist.Exit.jk == Ijk_Call
7184           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
7185          if (env->chainingAllowed) {
7186             /* .. almost always true .. */
7187             /* Skip the event check at the dst if this is a forwards
7188                edge. */
7189             Bool toFastEP
7190                = mode64
7191                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
7192                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
7193             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
7194             addInstr(env, MIPSInstr_XDirect(
7195                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
7196                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
7197                              amPC, cc, toFastEP));
7198          } else {
7199             /* .. very occasionally .. */
7200             /* We can't use chaining, so ask for an assisted transfer,
7201                as that's the only alternative that is allowable. */
7202             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
7203             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
7204          }
7205          return;
7206       }
7207 
7208       /* Case: assisted transfer to arbitrary address */
7209       switch (stmt->Ist.Exit.jk) {
7210          /* Keep this list in sync with that in iselNext below */
7211          case Ijk_ClientReq:
7212          case Ijk_EmFail:
7213          case Ijk_EmWarn:
7214          case Ijk_NoDecode:
7215          case Ijk_NoRedir:
7216          case Ijk_SigBUS:
7217          case Ijk_Yield:
7218          case Ijk_SigTRAP:
7219          case Ijk_SigFPE_IntDiv:
7220          case Ijk_SigFPE_IntOvf:
7221          case Ijk_Sys_syscall:
7222          case Ijk_InvalICache:
7223          {
7224             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
7225             addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
7226                                              stmt->Ist.Exit.jk));
7227             return;
7228          }
7229          default:
7230             break;
7231       }
7232 
7233       /* Do we ever expect to see any other kind? */
7234       goto stmt_fail;
7235    }
7236 
7237    default:
7238       break;
7239    }
7240 
7241    stmt_fail:
7242       vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
7243       ppIRStmt(stmt);
7244       vpanic("iselStmt:\n");
7245 }
7246 
7247 /*---------------------------------------------------------*/
7248 /*--- ISEL: Basic block terminators (Nexts)             ---*/
7249 /*---------------------------------------------------------*/
7250 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP)7251 static void iselNext ( ISelEnv* env,
7252                        IRExpr* next, IRJumpKind jk, Int offsIP )
7253 {
7254    if (vex_traceflags & VEX_TRACE_VCODE) {
7255       vex_printf( "\n-- PUT(%d) = ", offsIP);
7256       ppIRExpr( next );
7257       vex_printf( "; exit-");
7258       ppIRJumpKind(jk);
7259       vex_printf( "\n");
7260    }
7261 
7262    /* Case: boring transfer to known address */
7263    if (next->tag == Iex_Const) {
7264       IRConst* cdst = next->Iex.Const.con;
7265       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
7266       if (jk == Ijk_Boring || jk == Ijk_Call) {
7267          /* Boring transfer to known address */
7268          MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
7269          if (env->chainingAllowed) {
7270             /* .. almost always true .. */
7271             /* Skip the event check at the dst if this is a forwards
7272                edge. */
7273             Bool toFastEP
7274                = env->mode64
7275                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
7276                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
7277             if (0) vex_printf("%s", toFastEP ? "X" : ".");
7278             addInstr(env, MIPSInstr_XDirect(
7279                              env->mode64 ? (Addr64)cdst->Ico.U64
7280                                          : (Addr64)cdst->Ico.U32,
7281                              amPC, MIPScc_AL, toFastEP));
7282          } else {
7283             /* .. very occasionally .. */
7284             /* We can't use chaining, so ask for an assisted transfer,
7285                as that's the only alternative that is allowable. */
7286             HReg r = iselWordExpr_R(env, next);
7287             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
7288                                               Ijk_Boring));
7289          }
7290          return;
7291       }
7292    }
7293 
7294    /* Case: call/return (==boring) transfer to any address */
7295    switch (jk) {
7296       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
7297          HReg       r     = iselWordExpr_R(env, next);
7298          MIPSAMode*  amPC = MIPSAMode_IR(offsIP,
7299                                          GuestStatePointer(env->mode64));
7300          if (env->chainingAllowed) {
7301             addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
7302          } else {
7303             addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
7304                                               Ijk_Boring));
7305          }
7306          return;
7307       }
7308       default:
7309          break;
7310    }
7311 
7312    /* Case: assisted transfer to arbitrary address */
7313    switch (jk) {
7314       /* Keep this list in sync with that for Ist_Exit above */
7315       case Ijk_ClientReq:
7316       case Ijk_EmFail:
7317       case Ijk_EmWarn:
7318       case Ijk_NoDecode:
7319       case Ijk_NoRedir:
7320       case Ijk_SigBUS:
7321       case Ijk_SigILL:
7322       case Ijk_SigTRAP:
7323       case Ijk_SigFPE_IntDiv:
7324       case Ijk_SigFPE_IntOvf:
7325       case Ijk_Sys_syscall:
7326       case Ijk_InvalICache: {
7327          HReg      r     = iselWordExpr_R(env, next);
7328          MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
7329          addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
7330          return;
7331       }
7332       default:
7333          break;
7334    }
7335 
7336    vex_printf("\n-- PUT(%d) = ", offsIP);
7337    ppIRExpr(next );
7338    vex_printf("; exit-");
7339    ppIRJumpKind(jk);
7340    vex_printf("\n");
7341    vassert(0);  /* are we expecting any other kind? */
7342 }
7343 
7344 /*---------------------------------------------------------*/
7345 /*--- Insn selector top-level                           ---*/
7346 /*---------------------------------------------------------*/
7347 
7348 /* Translate an entire BB to mips code. */
iselSB_MIPS(const IRSB * bb,VexArch arch_host,const VexArchInfo * archinfo_host,const VexAbiInfo * vbi,Int offs_Host_EvC_Counter,Int offs_Host_EvC_FailAddr,Bool chainingAllowed,Bool addProfInc,Addr max_ga)7349 HInstrArray *iselSB_MIPS ( const IRSB* bb,
7350                            VexArch arch_host,
7351                            const VexArchInfo* archinfo_host,
7352                            const VexAbiInfo* vbi,
7353                            Int offs_Host_EvC_Counter,
7354                            Int offs_Host_EvC_FailAddr,
7355                            Bool chainingAllowed,
7356                            Bool addProfInc,
7357                            Addr max_ga )
7358 {
7359    Int      i, j;
7360    HReg     hreg, hregHI;
7361    ISelEnv* env;
7362    MIPSAMode *amCounter, *amFailAddr;
7363 
7364    hwcaps_host = archinfo_host->hwcaps;
7365 
7366    /* sanity ... */
7367    vassert(arch_host == VexArchMIPS32 || arch_host == VexArchMIPS64);
7368    vassert(VEX_PRID_COMP_MIPS == VEX_MIPS_COMP_ID(hwcaps_host)
7369            || VEX_PRID_COMP_CAVIUM == VEX_MIPS_COMP_ID(hwcaps_host)
7370            || VEX_PRID_COMP_BROADCOM == VEX_MIPS_COMP_ID(hwcaps_host)
7371            || VEX_PRID_COMP_NETLOGIC == VEX_MIPS_COMP_ID(hwcaps_host)
7372            || VEX_PRID_COMP_INGENIC_E1 == VEX_MIPS_COMP_ID(hwcaps_host)
7373            || VEX_PRID_COMP_LEGACY == VEX_MIPS_COMP_ID(hwcaps_host));
7374 
7375    /* Check that the host's endianness is as expected. */
7376    vassert(archinfo_host->endness == VexEndnessLE
7377            || archinfo_host->endness == VexEndnessBE);
7378 
7379    mode64 = arch_host != VexArchMIPS32;
7380    fp_mode64 = VEX_MIPS_HOST_FP_MODE(hwcaps_host);
7381    has_msa = VEX_MIPS_PROC_MSA(archinfo_host->hwcaps);
7382 
7383    /* Make up an initial environment to use. */
7384    env = LibVEX_Alloc_inline(sizeof(ISelEnv));
7385    env->vreg_ctr = 0;
7386    env->mode64 = mode64;
7387    env->fp_mode64 = fp_mode64;
7388 
7389    /* Set up output code array. */
7390    env->code = newHInstrArray();
7391 
7392    /* Copy BB's type env. */
7393    env->type_env = bb->tyenv;
7394 
7395    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
7396       change as we go along. */
7397    env->n_vregmap = bb->tyenv->types_used;
7398    env->vregmap = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7399    env->vregmapHI = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7400 
7401    /* and finally ... */
7402    env->hwcaps          = hwcaps_host;
7403    env->chainingAllowed = chainingAllowed;
7404    env->hwcaps          = hwcaps_host;
7405    env->max_ga          = max_ga;
7406 
7407    /* For each IR temporary, allocate a suitably-kinded virtual
7408       register. */
7409    j = 0;
7410    for (i = 0; i < env->n_vregmap; i++) {
7411       hregHI = hreg = INVALID_HREG;
7412       switch (bb->tyenv->types[i]) {
7413          case Ity_I1:
7414          case Ity_I8:
7415          case Ity_I16:
7416          case Ity_I32:
7417             if (mode64) {
7418                hreg = mkHReg(True, HRcInt64, 0, j++);
7419                break;
7420             } else {
7421                hreg = mkHReg(True, HRcInt32, 0, j++);
7422                break;
7423             }
7424          case Ity_I64:
7425             if (mode64) {
7426                hreg = mkHReg(True, HRcInt64, 0, j++);
7427                break;
7428             } else {
7429                hreg   = mkHReg(True, HRcInt32, 0, j++);
7430                hregHI = mkHReg(True, HRcInt32, 0, j++);
7431                break;
7432             }
7433          case Ity_I128:
7434             vassert(mode64);
7435             hreg   = mkHReg(True, HRcInt64, 0, j++);
7436             hregHI = mkHReg(True, HRcInt64, 0, j++);
7437             break;
7438          case Ity_F32:
7439             if (mode64) {
7440                hreg = mkHReg(True, HRcFlt64, 0, j++);
7441                break;
7442             } else {
7443                hreg = mkHReg(True, HRcFlt32, 0, j++);
7444                break;
7445             }
7446          case Ity_F64:
7447             hreg = mkHReg(True, HRcFlt64, 0, j++);
7448             break;
7449          case Ity_V128:
7450             hreg = mkHReg(True, HRcVec128, 0, j++);
7451             break;
7452          default:
7453             ppIRType(bb->tyenv->types[i]);
7454             vpanic("iselBB(mips): IRTemp type");
7455             break;
7456       }
7457       env->vregmap[i] = hreg;
7458       env->vregmapHI[i] = hregHI;
7459    }
7460    env->vreg_ctr = j;
7461 
7462    /* The very first instruction must be an event check. */
7463    amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, GuestStatePointer(mode64));
7464    amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, GuestStatePointer(mode64));
7465    addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
7466 
7467    /* Possibly a block counter increment (for profiling).  At this
7468       point we don't know the address of the counter, so just pretend
7469       it is zero.  It will have to be patched later, but before this
7470       translation is used, by a call to LibVEX_patchProfCtr. */
7471    if (addProfInc) {
7472       addInstr(env, MIPSInstr_ProfInc());
7473    }
7474 
7475    /* Ok, finally we can iterate over the statements. */
7476    for (i = 0; i < bb->stmts_used; i++)
7477       iselStmt(env, bb->stmts[i]);
7478 
7479    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
7480 
7481    /* record the number of vregs we used. */
7482    env->code->n_vregs = env->vreg_ctr;
7483    return env->code;
7484 
7485 }
7486 
7487 /*---------------------------------------------------------------*/
7488 /*--- end                                    host_mips_isel.c ---*/
7489 /*---------------------------------------------------------------*/
7490