Advance the head to 3.16.0.GIT.
[valgrind.git] / VEX / priv / host_mips_isel.c
blobc0cdfb084a5bd0144d5aa2a4263cc57b661af5f7
2 /*---------------------------------------------------------------*/
3 /*--- begin host_mips_isel.c ---*/
4 /*---------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2010-2017 RT-RK
11 mips-valgrind@rt-rk.com
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.
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.
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.
28 The GNU General Public License is contained in the file COPYING.
31 #include "libvex_basictypes.h"
32 #include "libvex_ir.h"
33 #include "libvex.h"
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"
41 /*---------------------------------------------------------*/
42 /*--- Register Usage Conventions ---*/
43 /*---------------------------------------------------------*/
45 /* Integer Regs
46 ------------
47 ZERO0 Reserved
48 GPR12:22 Allocateable
49 23 GuestStatePointer
50 SP StackFramePointer
51 RA LinkRegister */
53 static Bool mode64 = False;
55 /* Host CPU has FPU and 32 dbl. prec. FP registers. */
56 static Bool fp_mode64 = False;
58 /* Host hwcaps */
59 static UInt hwcaps_host = 0;
61 /* Host CPU has MSA ASE */
62 static Bool has_msa = False;
64 /* GPR register class for mips32/64 */
65 #define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
67 /* FPR register class for mips32/64 */
68 #define HRcFPR(_mode64) ((_mode64) ? HRcFlt64 : HRcFlt32)
70 /*---------------------------------------------------------*/
71 /*--- ISelEnv ---*/
72 /*---------------------------------------------------------*/
74 /* This carries around:
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.
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.
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.
92 - The code array, that is, the insns selected so far.
94 - A counter, for generating new virtual registers.
96 - The host subarchitecture we are selecting insns for.
97 This is set at the start and does not change.
99 - A Bool for indicating whether we may generate chain-me
100 instructions for control flow transfers, or whether we must use
101 XAssisted.
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.
111 Note, this is all (well, mostly) host-independent.
114 typedef
115 struct {
116 /* Constant -- are set at the start and do not change. */
117 IRTypeEnv* type_env;
119 HReg* vregmap;
120 HReg* vregmapHI;
121 Int n_vregmap;
123 UInt hwcaps;
124 Bool mode64;
125 Bool fp_mode64;
127 Bool chainingAllowed;
128 Addr64 max_ga;
130 /* These are modified as we go along. */
131 HInstrArray* code;
132 Int vreg_ctr;
134 ISelEnv;
136 static HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
138 vassert(tmp < env->n_vregmap);
139 return env->vregmap[tmp];
142 static void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
144 vassert(tmp < env->n_vregmap);
145 vassert(! hregIsInvalid(env->vregmapHI[tmp]));
146 *vrLO = env->vregmap[tmp];
147 *vrHI = env->vregmapHI[tmp];
150 static void
151 lookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
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];
160 static void addInstr(ISelEnv * env, MIPSInstr * instr)
162 addHInstr(env->code, instr);
163 if (vex_traceflags & VEX_TRACE_VCODE) {
164 ppMIPSInstr(instr, mode64);
165 vex_printf("\n");
169 static HReg newVRegI(ISelEnv * env)
171 HReg reg = mkHReg(True/*virtual reg*/,
172 HRcGPR(env->mode64), 0/*enc*/, env->vreg_ctr);
173 env->vreg_ctr++;
174 return reg;
177 static HReg newVRegD(ISelEnv * env)
179 HReg reg = mkHReg(True/*virtual reg*/,
180 HRcFlt64, 0/*enc*/, env->vreg_ctr);
181 env->vreg_ctr++;
182 return reg;
185 static HReg newVRegF(ISelEnv * env)
187 HReg reg = mkHReg(True/*virtual reg*/,
188 HRcFPR(env->mode64), 0/*enc*/, env->vreg_ctr);
189 env->vreg_ctr++;
190 return reg;
193 static HReg newVRegV ( ISelEnv* env )
195 HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0, env->vreg_ctr);
196 env->vreg_ctr++;
197 return reg;
200 static void add_to_sp(ISelEnv * env, UInt n)
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))));
212 static void sub_from_sp(ISelEnv * env, UInt n)
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))));
224 /*---------------------------------------------------------*/
225 /*--- ISEL: Forward declarations ---*/
226 /*---------------------------------------------------------*/
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.
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.
241 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
242 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
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);
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);
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);
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);
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);
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);
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);
277 static HReg iselV128Expr( ISelEnv* env, IRExpr* e );
278 static HReg iselV128Expr_wrk( ISelEnv* env, IRExpr* e );
280 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
281 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
283 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
284 static HReg iselDblExpr(ISelEnv * env, IRExpr * e);
286 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
287 static HReg iselFltExpr(ISelEnv * env, IRExpr * e);
289 static void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
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
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;
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));
314 /* store old FCSR to stack */
315 addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
317 /* set new value of FCSR */
318 addInstr(env, MIPSInstr_MtFCSR(tmp));
321 static void set_MIPS_rounding_mode_MSA(ISelEnv * env, IRExpr * mode) {
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
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));
352 static void set_guest_MIPS_rounding_mode_MSA(ISelEnv * env) {
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
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));
381 static void set_MIPS_rounding_default(ISelEnv * env)
383 HReg fcsr = newVRegI(env);
384 /* load as float */
385 MIPSAMode *am_addr;
386 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
388 addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
390 add_to_sp(env, 8); /* Reset SP */
392 /* set new value of FCSR*/
393 addInstr(env, MIPSInstr_MtFCSR(fcsr));
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));
408 /*---------------------------------------------------------*/
409 /*--- ISEL: Misc helpers ---*/
410 /*---------------------------------------------------------*/
412 /* Make an int reg-reg move. */
413 static MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
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));
420 /*---------------------------------------------------------*/
421 /*--- ISEL: Function call helpers ---*/
422 /*---------------------------------------------------------*/
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).
429 static Bool mightRequireFixedRegs(IRExpr * e)
431 switch (e->tag) {
432 case Iex_RdTmp:
433 case Iex_Const:
434 case Iex_Get:
435 return False;
436 default:
437 return True;
441 /* Load 2*I32 regs to fp reg */
442 static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
444 HReg fr_dst = newVRegD(env);
445 MIPSAMode *am_addr0, *am_addr1;
447 vassert(hregClass(r_srcHi) == HRcInt32);
448 vassert(hregClass(r_srcLo) == HRcInt32);
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));
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
467 /* load as float */
468 addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
470 add_to_sp(env, 16); /* Reset SP */
471 return fr_dst;
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. */
481 static void doHelperCall(/*OUT*/UInt* stackAdjustAfterCall,
482 /*OUT*/RetLoc* retloc,
483 ISelEnv* env,
484 IRExpr* guard,
485 IRCallee* cee, IRType retTy, IRExpr** args )
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;
495 /* Set default returns. We'll update them later if needed. */
496 *stackAdjustAfterCall = 0;
497 *retloc = mk_RetLoc_INVALID();
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;
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. */
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. */
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.
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. */
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++;
536 n_args++;
539 if (n_args > MIPS_N_REGPARMS) {
540 vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
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;
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. */
567 go_fast = True;
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;
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;
585 if (go_fast) {
586 for (i = 0; i < n_args; i++) {
587 if (mightRequireFixedRegs(args[i])) {
588 go_fast = False;
589 break;
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;
600 for (i = 0; i < n_args; i++) {
601 IRExpr* arg = args[i];
602 vassert(argreg < MIPS_N_REGPARMS);
604 IRType aTy = Ity_INVALID;
605 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
606 aTy = typeOfIRExpr(env->type_env, arg);
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));
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);
635 /* Fast scheme only applies for unconditional calls. Hence: */
636 cc = MIPScc_AL;
637 } else {
638 /* SLOW SCHEME; move via temporaries */
639 argreg = 0;
641 for (i = 0; i < n_args; i++) {
642 vassert(argreg < MIPS_N_REGPARMS);
643 IRExpr* arg = args[i];
645 IRType aTy = Ity_INVALID;
646 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
647 aTy = typeOfIRExpr(env->type_env, arg);
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++;
667 else if (arg->tag == Iex_VECRET) {
668 tmpregs[argreg++] = StackPointer(mode64);
669 sub_from_sp(env, 16); /* Move SP down 16 bytes */
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);
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]));
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);
730 Addr64 target = mode64 ? (Addr)cee->addr :
731 toUInt((Addr)cee->addr);
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));
742 /*---------------------------------------------------------*/
743 /*--- ISEL: Integer expression auxiliaries ---*/
744 /*---------------------------------------------------------*/
746 /* --------------------- AMODEs --------------------- */
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.
753 static Bool uInt_fits_in_16_bits(UInt u)
755 Int i = u & 0xFFFF;
756 i <<= 16;
757 i >>= 16;
758 return toBool(u == (UInt) i);
761 static Bool uLong_fits_in_16_bits ( ULong u )
763 Long i = u & 0xFFFFULL;
764 i <<= 48;
765 i >>= 48;
766 return toBool(u == (ULong) i);
769 static Bool uLong_is_4_aligned ( ULong u )
771 return toBool((u & 3ULL) == 0);
774 static Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
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");
791 static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
793 MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
794 vassert(sane_AMode(env, am));
795 return am;
798 /* DO NOT CALL THIS DIRECTLY ! */
799 static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
800 IRType xferTy)
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);
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));
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);
824 } else {
825 vassert(ty == Ity_I32);
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));
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);
842 return MIPSAMode_RR(r_idx, r_base);
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));
851 /*---------------------------------------------------------*/
852 /*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/
853 /*---------------------------------------------------------*/
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.
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.
869 static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
871 HReg r = iselWordExpr_R_wrk(env, e);
872 /* sanity checks ... */
874 vassert(hregClass(r) == HRcGPR(env->mode64));
875 vassert(hregIsVirtual(r));
876 return r;
879 /* DO NOT CALL THIS DIRECTLY ! */
880 static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
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));
888 switch (e->tag) {
889 /* --------- TEMP --------- */
890 case Iex_RdTmp:
891 return lookupIRTemp(env, e->Iex.RdTmp.tmp);
893 /* --------- LOAD --------- */
894 case Iex_Load: {
895 HReg r_dst = newVRegI(env);
896 MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
898 if (e->Iex.Load.end != Iend_LE
899 && e->Iex.Load.end != Iend_BE)
900 goto irreducible;
902 addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
903 r_dst, am_addr, mode64));
904 return r_dst;
907 /* --------- BINARY OP --------- */
908 case Iex_Binop: {
909 MIPSAluOp aluOp;
910 MIPSShftOp shftOp;
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;
920 case Iop_Sub8:
921 case Iop_Sub16:
922 case Iop_Sub32:
923 aluOp = Malu_SUB;
924 break;
926 case Iop_Sub64:
927 aluOp = Malu_DSUB;
928 break;
930 case Iop_And8:
931 case Iop_And16:
932 case Iop_And32:
933 case Iop_And64:
934 aluOp = Malu_AND;
935 break;
937 case Iop_Or8:
938 case Iop_Or16:
939 case Iop_Or32:
940 case Iop_Or64:
941 aluOp = Malu_OR;
942 break;
944 case Iop_Xor8:
945 case Iop_Xor16:
946 case Iop_Xor32:
947 case Iop_Xor64:
948 aluOp = Malu_XOR;
949 break;
951 case Iop_Add64:
952 aluOp = Malu_DADD;
953 break;
955 default:
956 aluOp = Malu_INVALID;
957 break;
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");
984 addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
985 return r_dst;
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;
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);
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);
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
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;
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;
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) {
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);
1109 MIPSCondCode cc;
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");
1167 addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
1168 return dst;
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 */
1182 addInstr(env, MIPSInstr_Alu(Malu_SLT, tmp, argL, argRH));
1183 #if (__mips_isa_rev >= 6)
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)));
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;
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;
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;
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)));
1250 addInstr(env, MIPSInstr_Mult(False, r_tmpL, r_tmpR));
1251 addInstr(env, MIPSInstr_Mflo(r_tmpR));
1252 #endif
1253 return r_tmpR;
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)));
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));
1300 } else {
1301 addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
1302 addInstr(env, MIPSInstr_Mflo(r_dst));
1304 #endif
1305 return r_dst;
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);
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);
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)));
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
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)));
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)));
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)));
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
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
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);
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)));
1481 addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1482 addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1483 MIPSRH_Reg(mask)));
1485 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1486 MIPSRH_Reg(tLo_1)));
1488 return r_dst;
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;
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;
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;
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);
1555 addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
1556 MIPSRH_Imm(False, 32)));
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)));
1564 return r_dst;
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);
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);
1578 /* Doubleword Move from Floating Point
1579 dmfc1 valS, tmpF */
1580 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
1582 return valS;
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);
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);
1596 /* Doubleword Move from Floating Point
1597 dmfc1 valS, tmpF */
1598 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
1600 return valS;
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);
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);
1617 /* Move Word From Floating Point
1618 mfc1 r_dst, valS */
1619 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1621 return r_dst;
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;
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);
1635 sub_from_sp(env, 16); /* Move SP down 16 bytes */
1636 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
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
1649 /* Reset SP */
1650 add_to_sp(env, 16);
1652 return r_dst;
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;
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;
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;
1694 return r_dst;
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;
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;
1723 return r_dst;
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;
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;
1750 return r_dst;
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;
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;
1778 return r_dst;
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);
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);
1790 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1792 return r_dst;
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;
1811 /* What's the retloc? */
1812 RetLoc rloc = mk_RetLoc_INVALID();
1813 if (ty == Ity_I32) {
1814 rloc = mk_RetLoc_simple(RLPri_Int);
1816 else if (ty == Ity_I64) {
1817 rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
1818 mk_RetLoc_simple(RLPri_2Int);
1820 else {
1821 goto irreducible;
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;
1838 break;
1841 /* --------- UNARY OP --------- */
1842 case Iex_Unop: {
1843 IROp op_unop = e->Iex.Unop.op;
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);
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;
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);
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;
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);
1926 addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
1927 return r_dst;
1930 case Iop_ReinterpF32asI32: {
1931 HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1932 HReg r_dst = newVRegI(env);
1934 /* Move Word From Floating Point
1935 mfc1 r_dst, fr_src */
1936 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, fr_src));
1938 return r_dst;
1941 case Iop_ReinterpF64asI64: {
1942 vassert(mode64);
1943 HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1944 HReg r_dst = newVRegI(env);
1946 /* Doubleword Move from Floating Point
1947 mfc1 r_dst, fr_src */
1948 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, r_dst, fr_src));
1950 return r_dst;
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);
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);
1966 /* Move Word From Floating Point
1967 mfc1 r_dst, valS */
1968 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1970 return r_dst;
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);
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;
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);
1998 addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
1999 MIPSRH_Imm(False, mask)));
2000 return r_dst;
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;
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 /* fallthrough */
2026 case Iop_1Uto8:
2027 case Iop_1Uto32:
2028 mask = toUShort(0x1);
2029 break;
2030 case Iop_8Uto64:
2031 vassert(mode64);
2032 /* fallthrough */
2033 case Iop_8Uto16:
2034 case Iop_8Uto32:
2035 mask = toUShort(0xFF);
2036 break;
2037 case Iop_16Uto64:
2038 vassert(mode64);
2039 /* fallthrough */
2040 case Iop_16Uto32:
2041 mask = toUShort(0xFFFF);
2042 break;
2043 default:
2044 vassert(0);
2045 break;
2047 addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
2048 MIPSRH_Imm(False, mask)));
2049 return r_dst;
2052 case Iop_32Uto64: {
2053 HReg r_dst = newVRegI(env);
2054 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2055 vassert(mode64);
2056 addInstr(env, MIPSInstr_Shft(Mshft_SLL, False /*!32bit shift */,
2057 r_dst, r_src, MIPSRH_Imm(False, 32)));
2058 addInstr(env, MIPSInstr_Shft(Mshft_SRL, False /*!32bit shift */,
2059 r_dst, r_dst, MIPSRH_Imm(False, 32)));
2060 return r_dst;
2063 case Iop_64HIto32: {
2064 if (env->mode64) {
2065 HReg r_dst = newVRegI(env);
2066 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2067 addInstr(env, MIPSInstr_Shft(Mshft_SRA, False /*64bit shift */,
2068 r_dst, r_src, MIPSRH_Imm(True, 32)));
2069 return r_dst;
2070 } else {
2071 HReg rHi, rLo;
2072 iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2073 return rHi;
2077 case Iop_64to32: {
2078 if (env->mode64) {
2079 HReg r_dst = newVRegI(env);
2080 r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
2081 return r_dst;
2082 } else {
2083 HReg rHi, rLo;
2084 iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2085 return rLo;
2089 case Iop_64to16: {
2090 vassert(env->mode64);
2091 HReg r_dst = newVRegI(env);
2092 r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
2093 return r_dst;
2096 case Iop_32Sto64: {
2097 HReg r_dst = newVRegI(env);
2098 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2099 vassert(mode64);
2100 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*!32bit shift */,
2101 r_dst, r_src, MIPSRH_Imm(True, 0)));
2102 return r_dst;
2105 case Iop_CmpNEZ8:
2106 case Iop_CmpNEZ16: {
2107 HReg r_dst = newVRegI(env);
2108 HReg tmp = newVRegI(env);
2109 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2110 UShort mask = (op_unop == Iop_CmpNEZ8) ? 0xFF : 0xFFFF;
2112 addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
2113 MIPSRH_Imm(False, mask)));
2114 addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
2115 hregMIPS_GPR0(mode64), MIPScc_NE));
2116 return r_dst;
2119 case Iop_CmpNEZ32: {
2120 HReg r_dst = newVRegI(env);
2121 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2123 addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
2124 hregMIPS_GPR0(mode64), MIPScc_NE));
2125 return r_dst;
2128 case Iop_CmpwNEZ32: {
2129 HReg r_dst = newVRegI(env);
2130 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2132 addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
2133 MIPSRH_Reg(r_src)));
2135 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2136 MIPSRH_Reg(r_src)));
2137 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
2138 MIPSRH_Imm(False, 31)));
2139 return r_dst;
2142 case Iop_Left8:
2143 case Iop_Left16:
2144 case Iop_Left32:
2145 case Iop_Left64: {
2146 if (op_unop == Iop_Left64 && !mode64)
2147 goto irreducible;
2148 HReg r_dst = newVRegI(env);
2149 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2150 MIPSAluOp op = (op_unop == Iop_Left64) ? Malu_DSUB : Malu_SUB;
2151 addInstr(env, MIPSInstr_Alu(op, r_dst,
2152 hregMIPS_GPR0(mode64),
2153 MIPSRH_Reg(r_src)));
2154 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2155 MIPSRH_Reg(r_src)));
2156 return r_dst;
2159 case Iop_Clz64:
2160 vassert(mode64);
2161 /* fallthrough */
2162 case Iop_Clz32: {
2163 HReg r_dst = newVRegI(env);
2164 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2165 MIPSUnaryOp op = (op_unop == Iop_Clz64) ? Mun_DCLZ : Mun_CLZ;
2166 addInstr(env, MIPSInstr_Unary(op, r_dst, r_src));
2167 return r_dst;
2170 case Iop_CmpNEZ64: {
2171 HReg hi, lo;
2172 HReg r_dst = newVRegI(env);
2173 HReg r_src;
2174 if (env->mode64) {
2175 r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2176 } else {
2177 r_src = newVRegI(env);
2178 iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
2179 addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
2181 addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
2182 hregMIPS_GPR0(mode64), MIPScc_NE));
2183 return r_dst;
2186 case Iop_CmpwNEZ64: {
2187 HReg tmp1;
2188 HReg tmp2 = newVRegI(env);
2189 vassert(env->mode64);
2190 tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
2192 addInstr(env, MIPSInstr_Alu(Malu_DSUB, tmp2, hregMIPS_GPR0(mode64),
2193 MIPSRH_Reg(tmp1)));
2195 addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
2196 addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
2197 MIPSRH_Imm (False, 63)));
2198 return tmp2;
2201 case Iop_128HIto64: {
2202 vassert(mode64);
2203 HReg rHi, rLo;
2204 iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2205 return rHi; /* and abandon rLo .. poor wee thing :-) */
2208 case Iop_128to64: {
2209 vassert(mode64);
2210 HReg rHi, rLo;
2211 iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2212 return rLo; /* and abandon rLo .. poor wee thing :-) */
2215 case Iop_V128to32: {
2216 HReg i_dst = newVRegI(env);
2217 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2218 vassert(has_msa);
2219 addInstr(env,
2220 MIPSInstr_MsaElm(MSA_COPY_S, v_src, i_dst, MSA_DFN_W));
2221 return i_dst;
2224 case Iop_V128HIto64: {
2225 vassert(mode64);
2226 vassert(has_msa);
2227 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2228 HReg reg = newVRegI(env);
2229 addInstr(env,
2230 MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 1));
2231 return reg;
2234 case Iop_V128to64: {
2235 vassert(mode64);
2236 vassert(has_msa);
2237 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2238 HReg reg = newVRegI(env);
2239 addInstr(env,
2240 MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 0));
2241 return reg;
2244 case Iop_F32toF16x4_DEP: {
2245 vassert(mode64);
2246 vassert(has_msa);
2247 HReg v_arg = iselV128Expr(env, e->Iex.Unop.arg);
2248 HReg v_src = newVRegV(env);
2249 set_guest_MIPS_rounding_mode_MSA(env);
2250 addInstr(env,
2251 MIPSInstr_Msa3RF(MSA_FEXDO, MSA_F_WH,
2252 v_src, v_arg, v_arg));
2253 set_MIPS_rounding_default_MSA(env);
2254 HReg reg = newVRegI(env);
2255 addInstr(env,
2256 MIPSInstr_MsaElm(MSA_COPY_S, v_src, reg, MSA_DFN_D | 0));
2257 return reg;
2261 default:
2262 break;
2265 /* -------- DSP ASE -------- */
2266 /* All Unop cases involving host-side helper calls. */
2267 void* fn = NULL;
2268 switch (e->Iex.Unop.op) {
2269 case Iop_CmpNEZ16x2:
2270 fn = &h_generic_calc_CmpNEZ16x2; break;
2271 case Iop_CmpNEZ8x4:
2272 fn = &h_generic_calc_CmpNEZ8x4; break;
2273 default:
2274 break;
2277 RetLoc rloc = mk_RetLoc_INVALID();
2278 if (ty == Ity_I32) {
2279 rloc = mk_RetLoc_simple(RLPri_Int);
2281 else if (ty == Ity_I64) {
2282 rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
2283 mk_RetLoc_simple(RLPri_2Int);
2285 else {
2286 goto irreducible;
2289 if (fn) {
2290 HReg regL = iselWordExpr_R(env, e->Iex.Unop.arg);
2291 HReg res = newVRegI(env);
2292 addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
2293 argiregs |= (1 << 4);
2294 addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
2295 (Addr)fn,
2296 argiregs, rloc));
2297 addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
2298 return res;
2301 break;
2304 /* --------- GET --------- */
2305 case Iex_Get: {
2306 if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
2307 || ((ty == Ity_I64) && mode64)) {
2308 HReg r_dst = newVRegI(env);
2310 MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
2311 GuestStatePointer(mode64));
2312 addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
2313 mode64));
2314 return r_dst;
2316 break;
2319 /* --------- ITE --------- */
2320 case Iex_ITE: {
2321 if ((ty == Ity_I8 || ty == Ity_I16 ||
2322 ty == Ity_I32 || ((ty == Ity_I64))) &&
2323 typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
2324 HReg r0 = iselWordExpr_R(env, e->Iex.ITE.iffalse);
2325 HReg r1 = iselWordExpr_R(env, e->Iex.ITE.iftrue);
2326 HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
2327 HReg r_dst = newVRegI(env);
2329 * r_dst = r0
2330 * movn r_dst, r1, r_cond
2332 #if (__mips_isa_rev >= 6)
2333 HReg r_temp = newVRegI(env);
2334 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dst, r0, r_cond));
2335 addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, r1, r_cond));
2336 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
2337 MIPSRH_Reg(r_temp)));
2339 #else
2340 addInstr(env, mk_iMOVds_RR(r_dst, r0));
2341 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, r1, r_cond));
2342 #endif
2343 return r_dst;
2345 break;
2348 /* --------- LITERAL --------- */
2349 /* 32/16/8-bit literals */
2350 case Iex_Const: {
2351 Long l;
2352 HReg r_dst = newVRegI(env);
2353 IRConst *con = e->Iex.Const.con;
2354 switch (con->tag) {
2355 case Ico_U64:
2356 if (!mode64)
2357 goto irreducible;
2358 l = (Long) con->Ico.U64;
2359 break;
2360 case Ico_U32:
2361 l = (Long) (Int) con->Ico.U32;
2362 break;
2363 case Ico_U16:
2364 l = (Long) (Int) (Short) con->Ico.U16;
2365 break;
2366 case Ico_U8:
2367 l = (Long) (Int) (Char) con->Ico.U8;
2368 break;
2369 default:
2370 vpanic("iselIntExpr_R.const(mips)");
2372 addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
2373 return r_dst;
2376 /* --------- CCALL --------- */
2377 case Iex_CCall: {
2378 HReg r_dst = newVRegI(env);
2379 vassert(ty == e->Iex.CCall.retty);
2381 /* be very restrictive for now. Only 32/64-bit ints allowed for
2382 args, and 64 and 32 bits for return type. Don't forget to change
2383 the RetLoc if more return types are allowed in future. */
2384 if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32)
2385 goto irreducible;
2387 /* Marshal args, do the call, clear stack. */
2388 UInt addToSp = 0;
2389 RetLoc rloc = mk_RetLoc_INVALID();
2390 doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
2391 e->Iex.CCall.retty, e->Iex.CCall.args );
2393 vassert(is_sane_RetLoc(rloc));
2394 vassert(rloc.pri == RLPri_Int);
2395 vassert(addToSp == 0);
2396 addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
2397 return r_dst;
2400 #if (__mips_isa_rev >= 6)
2401 case Iex_Qop: {
2402 HReg dst = newVRegI(env);
2403 HReg src1 = iselWordExpr_R(env, e->Iex.Qop.details->arg1);
2404 HReg src2 = iselWordExpr_R(env, e->Iex.Qop.details->arg2);
2405 HReg src3 = iselWordExpr_R(env, e->Iex.Qop.details->arg3);
2406 HReg src4 = iselWordExpr_R(env, e->Iex.Qop.details->arg4);
2407 switch (e->Iex.Qop.details->op) {
2408 case Iop_Rotx32:
2409 addInstr(env, MIPSInstr_Bitswap(Rotx32, dst, src1, src2, src3, src4));
2410 break;
2411 case Iop_Rotx64:
2412 addInstr(env, MIPSInstr_Bitswap(Rotx64, dst, src1, src2, src3, src4));
2413 break;
2414 default:
2415 break;
2417 return dst;
2419 #endif
2421 default:
2422 break;
2423 } /* end switch(e->tag) */
2425 /* We get here if no pattern matched. */
2426 irreducible:
2427 vex_printf("--------------->\n");
2428 if (e->tag == Iex_RdTmp)
2429 vex_printf("Iex_RdTmp \n");
2430 ppIRExpr(e);
2432 vpanic("iselWordExpr_R(mips): cannot reduce tree");
2435 /* --------------------- RH --------------------- */
2437 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2438 (reg-or-halfword-immediate). It's important to specify whether the
2439 immediate is to be regarded as signed or not. If yes, this will
2440 never return -32768 as an immediate; this guaranteed that all
2441 signed immediates that are return can have their sign inverted if
2442 need be. */
2444 static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
2446 MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
2447 /* sanity checks ... */
2448 switch (ri->tag) {
2449 case Mrh_Imm:
2450 vassert(ri->Mrh.Imm.syned == syned);
2451 if (syned)
2452 vassert(ri->Mrh.Imm.imm16 != 0x8000);
2453 return ri;
2454 case Mrh_Reg:
2455 vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2456 vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2457 return ri;
2458 default:
2459 vpanic("iselIntExpr_RH: unknown mips RH tag");
2463 /* DO NOT CALL THIS DIRECTLY ! */
2464 static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
2466 ULong u;
2467 Long l;
2468 IRType ty = typeOfIRExpr(env->type_env, e);
2469 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
2470 ((ty == Ity_I64) && env->mode64));
2472 /* special case: immediate */
2473 if (e->tag == Iex_Const) {
2474 IRConst *con = e->Iex.Const.con;
2475 /* What value are we aiming to generate? */
2476 switch (con->tag) {
2477 /* Note: Not sign-extending - we carry 'syned' around */
2478 case Ico_U64:
2479 vassert(env->mode64);
2480 u = con->Ico.U64;
2481 break;
2482 case Ico_U32:
2483 u = 0xFFFFFFFF & con->Ico.U32;
2484 break;
2485 case Ico_U16:
2486 u = 0x0000FFFF & con->Ico.U16;
2487 break;
2488 case Ico_U8:
2489 u = 0x000000FF & con->Ico.U8;
2490 break;
2491 default:
2492 vpanic("iselIntExpr_RH.Iex_Const(mips)");
2494 l = (Long) u;
2495 /* Now figure out if it's representable. */
2496 if (!syned && u <= 65535) {
2497 return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
2499 if (syned && l >= -32767 && l <= 32767) {
2500 return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
2502 /* no luck; use the Slow Way. */
2504 /* default case: calculate into a register and return that */
2505 return MIPSRH_Reg(iselWordExpr_R(env, e));
2508 /* --------------------- RH5u --------------------- */
2510 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2511 being an immediate in the range 1 .. 31 inclusive. Used for doing
2512 shift amounts. */
2514 static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
2516 MIPSRH *ri;
2517 ri = iselWordExpr_RH5u_wrk(env, e);
2518 /* sanity checks ... */
2519 switch (ri->tag) {
2520 case Mrh_Imm:
2521 vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
2522 vassert(!ri->Mrh.Imm.syned);
2523 return ri;
2524 case Mrh_Reg:
2525 vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
2526 vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2527 return ri;
2528 default:
2529 vpanic("iselIntExpr_RH5u: unknown mips RH tag");
2533 /* DO NOT CALL THIS DIRECTLY ! */
2534 static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
2536 IRType ty = typeOfIRExpr(env->type_env, e);
2537 vassert(ty == Ity_I8);
2539 /* special case: immediate */
2540 if (e->tag == Iex_Const
2541 && e->Iex.Const.con->tag == Ico_U8
2542 && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
2543 return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
2546 /* default case: calculate into a register and return that */
2547 return MIPSRH_Reg(iselWordExpr_R(env, e));
2550 /* --------------------- RH6u --------------------- */
2552 static MIPSRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
2554 MIPSRH *ri;
2555 ri = iselWordExpr_RH6u_wrk(env, e);
2556 /* sanity checks ... */
2557 switch (ri->tag) {
2558 case Mrh_Imm:
2559 vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 63);
2560 vassert(!ri->Mrh.Imm.syned);
2561 return ri;
2562 case Mrh_Reg:
2563 vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2564 vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2565 return ri;
2566 default:
2567 vpanic("iselIntExpr_RH6u: unknown RI tag");
2571 /* DO NOT CALL THIS DIRECTLY ! */
2572 static MIPSRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
2574 IRType ty = typeOfIRExpr(env->type_env, e);
2575 vassert(ty == Ity_I8);
2577 /* special case: immediate */
2578 if (e->tag == Iex_Const
2579 && e->Iex.Const.con->tag == Ico_U8
2580 && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
2582 return MIPSRH_Imm(False /*unsigned */ ,
2583 e->Iex.Const.con->Ico.U8);
2586 /* default case: calculate into a register and return that */
2587 return MIPSRH_Reg(iselWordExpr_R(env, e));
2589 /* --------------------- RH7u --------------------- */
2591 static MIPSRH *iselWordExpr_RH7u ( ISelEnv * env, IRExpr * e )
2593 MIPSRH *ri;
2594 ri = iselWordExpr_RH7u_wrk(env, e);
2595 /* sanity checks ... */
2596 switch (ri->tag) {
2597 case Mrh_Imm:
2598 vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 127);
2599 vassert(!ri->Mrh.Imm.syned);
2600 return ri;
2601 case Mrh_Reg:
2602 vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2603 vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2604 return ri;
2605 default:
2606 vpanic("iselIntExpr_RH7u: unknown RI tag");
2610 /* DO NOT CALL THIS DIRECTLY ! */
2611 static MIPSRH *iselWordExpr_RH7u_wrk ( ISelEnv * env, IRExpr * e )
2613 IRType ty = typeOfIRExpr(env->type_env, e);
2614 vassert(ty == Ity_I8);
2616 /* special case: immediate */
2617 if (e->tag == Iex_Const
2618 && e->Iex.Const.con->tag == Ico_U8
2619 && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 127)
2621 return MIPSRH_Imm(False /*unsigned */ ,
2622 e->Iex.Const.con->Ico.U8);
2625 /* default case: calculate into a register and return that */
2626 return MIPSRH_Reg(iselWordExpr_R(env, e));
2630 /* --------------------- CONDCODE --------------------- */
2632 /* Generate code to evaluated a bit-typed expression, returning the
2633 condition code which would correspond when the expression would
2634 notionally have returned 1. */
2636 static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
2638 MIPSCondCode cc = iselCondCode_wrk(env,e);
2639 vassert(cc != MIPScc_NV);
2640 return cc;
2643 /* DO NOT CALL THIS DIRECTLY ! */
2644 static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
2646 vassert(e);
2647 vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
2648 /* Cmp*32*(x,y) ? */
2649 if (e->Iex.Binop.op == Iop_CmpEQ32
2650 || e->Iex.Binop.op == Iop_CmpNE32
2651 || e->Iex.Binop.op == Iop_CmpNE64
2652 || e->Iex.Binop.op == Iop_CmpLT32S
2653 || e->Iex.Binop.op == Iop_CmpLT32U
2654 || e->Iex.Binop.op == Iop_CmpLT64U
2655 || e->Iex.Binop.op == Iop_CmpLE32S
2656 || e->Iex.Binop.op == Iop_CmpLE64S
2657 || e->Iex.Binop.op == Iop_CmpLT64S
2658 || e->Iex.Binop.op == Iop_CmpEQ64
2659 || e->Iex.Binop.op == Iop_CasCmpEQ32
2660 || e->Iex.Binop.op == Iop_CasCmpEQ64) {
2662 Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
2663 || e->Iex.Binop.op == Iop_CmpLE32S
2664 || e->Iex.Binop.op == Iop_CmpLT64S
2665 || e->Iex.Binop.op == Iop_CmpLE64S);
2666 Bool size32;
2667 HReg dst = newVRegI(env);
2668 HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2669 HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
2671 MIPSCondCode cc;
2673 switch (e->Iex.Binop.op) {
2674 case Iop_CmpEQ32:
2675 case Iop_CasCmpEQ32:
2676 cc = MIPScc_EQ;
2677 size32 = True;
2678 break;
2679 case Iop_CmpNE32:
2680 cc = MIPScc_NE;
2681 size32 = True;
2682 break;
2683 case Iop_CmpNE64:
2684 cc = MIPScc_NE;
2685 size32 = False;
2686 break;
2687 case Iop_CmpLT32S:
2688 cc = MIPScc_LT;
2689 size32 = True;
2690 break;
2691 case Iop_CmpLT32U:
2692 cc = MIPScc_LO;
2693 size32 = True;
2694 break;
2695 case Iop_CmpLT64U:
2696 cc = MIPScc_LO;
2697 size32 = False;
2698 break;
2699 case Iop_CmpLE32S:
2700 cc = MIPScc_LE;
2701 size32 = True;
2702 break;
2703 case Iop_CmpLE64S:
2704 cc = MIPScc_LE;
2705 size32 = False;
2706 break;
2707 case Iop_CmpLT64S:
2708 cc = MIPScc_LT;
2709 size32 = False;
2710 break;
2711 case Iop_CmpEQ64:
2712 case Iop_CasCmpEQ64:
2713 cc = MIPScc_EQ;
2714 size32 = False;
2715 break;
2716 default:
2717 vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
2718 break;
2721 addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
2722 /* Store result to guest_COND */
2723 MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2725 addInstr(env, MIPSInstr_Store(4,
2726 MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2727 am_addr->Mam.IR.base),
2728 dst, mode64));
2729 return cc;
2731 if (e->Iex.Binop.op == Iop_Not1) {
2732 HReg r_dst = newVRegI(env);
2733 HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
2734 MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
2736 addInstr(env, MIPSInstr_LI(r_dst, 0x1));
2737 addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
2738 /* Store result to guest_COND */
2739 MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2741 addInstr(env, MIPSInstr_Store(4,
2742 MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2743 am_addr->Mam.IR.base),
2744 r_dst, mode64));
2745 return MIPScc_NE;
2747 if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
2748 HReg r_dst = iselWordExpr_R_wrk(env, e);
2749 /* Store result to guest_COND */
2750 MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2752 addInstr(env, MIPSInstr_Store(4,
2753 MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2754 am_addr->Mam.IR.base),
2755 r_dst, mode64));
2756 return MIPScc_EQ;
2759 vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
2760 ppIRExpr(e);
2761 vpanic("iselCondCode(mips)");
2764 /*---------------------------------------------------------*/
2765 /*--- ISEL: Vector expressions (128 bit - SIMD) ---*/
2766 /*---------------------------------------------------------*/
2768 /* Compute a vector value into vector register. */
2769 static HReg iselV128Expr (ISelEnv* env, IRExpr* e) {
2770 vassert(has_msa);
2771 HReg r = iselV128Expr_wrk(env, e);
2772 vassert(hregClass(r) == HRcVec128);
2773 vassert(hregIsVirtual(r));
2774 return r;
2777 /* DO NOT CALL THIS DIRECTLY ! */
2778 static HReg iselV128Expr_wrk(ISelEnv* env, IRExpr* e) {
2779 IRType ty = typeOfIRExpr(env->type_env, e);
2780 vassert(e);
2781 vassert(ty == Ity_V128);
2783 if (e->tag == Iex_RdTmp) {
2784 return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2787 if (e->tag == Iex_Load) {
2788 vassert (e->Iex.Load.ty == Ity_V128);
2789 HReg v_dst = newVRegV(env);
2790 addInstr(env, MIPSInstr_MsaMi10(MSA_LD, 0, iselWordExpr_R(env,
2791 e->Iex.Load.addr), v_dst, MSA_B));
2792 return v_dst;
2795 if (e->tag == Iex_Get) {
2796 HReg v_dst = newVRegV(env);
2797 #if defined(_MIPSEB)
2798 HReg r_addr = newVRegI(env);
2799 addInstr(env, MIPSInstr_Alu(mode64 ? Malu_DADD : Malu_ADD, r_addr, GuestStatePointer(mode64),
2800 MIPSRH_Imm(False, e->Iex.Get.offset)));
2801 addInstr(env, MIPSInstr_MsaMi10(MSA_LD, 0, r_addr, v_dst, MSA_B));
2802 #else
2803 vassert(!(e->Iex.Get.offset & 7));
2804 addInstr(env, MIPSInstr_MsaMi10(MSA_LD, e->Iex.Get.offset >> 3,
2805 GuestStatePointer(mode64), v_dst, MSA_D));
2806 #endif
2807 return v_dst;
2810 if (e->tag == Iex_Unop) {
2811 IROp op_unop = e->Iex.Unop.op;
2813 switch (op_unop) {
2814 case Iop_Abs64x2: {
2815 HReg v_dst = newVRegV(env);
2816 HReg v_help = newVRegV(env);
2817 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2818 addInstr(env,
2819 MIPSInstr_Msa3R(MSA_SUBV, MSA_D, v_help, v_src, v_src));
2820 addInstr(env,
2821 MIPSInstr_Msa3R(MSA_ADD_A, MSA_D,
2822 v_dst, v_src, v_help));
2823 return v_dst;
2826 case Iop_Abs32x4: {
2827 HReg v_dst = newVRegV(env);
2828 HReg v_help = newVRegV(env);
2829 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2830 addInstr(env,
2831 MIPSInstr_Msa3R(MSA_SUBV, MSA_W, v_help, v_src, v_src));
2832 addInstr(env,
2833 MIPSInstr_Msa3R(MSA_ADD_A, MSA_W,
2834 v_dst, v_src, v_help));
2835 return v_dst;
2838 case Iop_Abs16x8: {
2839 HReg v_dst = newVRegV(env);
2840 HReg v_help = newVRegV(env);
2841 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2842 addInstr(env,
2843 MIPSInstr_Msa3R(MSA_SUBV, MSA_H, v_help, v_src, v_src));
2844 addInstr(env,
2845 MIPSInstr_Msa3R(MSA_ADD_A, MSA_H,
2846 v_dst, v_src, v_help));
2847 return v_dst;
2850 case Iop_Abs8x16: {
2851 HReg v_dst = newVRegV(env);
2852 HReg v_help = newVRegV(env);
2853 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2854 addInstr(env,
2855 MIPSInstr_Msa3R(MSA_SUBV, MSA_B, v_help, v_src, v_src));
2856 addInstr(env,
2857 MIPSInstr_Msa3R(MSA_ADD_A, MSA_B,
2858 v_dst, v_src, v_help));
2859 return v_dst;
2862 case Iop_Cnt8x16: {
2863 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2864 HReg res = newVRegV(env);
2865 addInstr(env, MIPSInstr_Msa2R(MSA_PCNT, MSA_B, v_src, res));
2866 return res;
2869 case Iop_NotV128: {
2870 HReg v_dst = newVRegV(env);
2871 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2872 addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_src, v_src));
2873 return v_dst;
2876 case Iop_Reverse8sIn16_x8: {
2877 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2878 HReg v_tmp = newVRegV(env);
2879 addInstr(env,
2880 MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2881 addInstr(env,
2882 MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2883 return v_src;
2886 case Iop_Reverse8sIn32_x4: {
2887 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2888 HReg v_tmp = newVRegV(env);
2889 addInstr(env,
2890 MIPSInstr_Msa3R(MSA_ILVEV, MSA_H, v_tmp, v_src, v_src));
2891 addInstr(env,
2892 MIPSInstr_Msa3R(MSA_ILVOD, MSA_H, v_src, v_tmp, v_src));
2893 addInstr(env,
2894 MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2895 addInstr(env,
2896 MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2897 return v_src;
2900 case Iop_Reverse8sIn64_x2: {
2901 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2902 HReg v_tmp = newVRegV(env);
2903 addInstr(env,
2904 MIPSInstr_Msa3R(MSA_ILVEV, MSA_W, v_tmp, v_src, v_src));
2905 addInstr(env,
2906 MIPSInstr_Msa3R(MSA_ILVOD, MSA_W, v_src, v_tmp, v_src));
2907 addInstr(env,
2908 MIPSInstr_Msa3R(MSA_ILVEV, MSA_H, v_tmp, v_src, v_src));
2909 addInstr(env,
2910 MIPSInstr_Msa3R(MSA_ILVOD, MSA_H, v_src, v_tmp, v_src));
2911 addInstr(env,
2912 MIPSInstr_Msa3R(MSA_ILVEV, MSA_B, v_tmp, v_src, v_src));
2913 addInstr(env,
2914 MIPSInstr_Msa3R(MSA_ILVOD, MSA_B, v_src, v_tmp, v_src));
2915 return v_src;
2918 case Iop_Cls8x16: {
2919 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2920 HReg v_dst = newVRegV(env);
2921 addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_B, v_src, v_dst));
2922 return v_dst;
2925 case Iop_Cls16x8: {
2926 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2927 HReg v_dst = newVRegV(env);
2928 addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_H, v_src, v_dst));
2929 return v_dst;
2932 case Iop_Cls32x4: {
2933 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2934 HReg v_dst = newVRegV(env);
2935 addInstr(env, MIPSInstr_Msa2R(MSA_NLOC, MSA_W, v_src, v_dst));
2936 return v_dst;
2939 case Iop_Clz8x16: {
2940 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2941 HReg v_dst = newVRegV(env);
2942 addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_B, v_src, v_dst));
2943 return v_dst;
2946 case Iop_Clz16x8: {
2947 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2948 HReg v_dst = newVRegV(env);
2949 addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_H, v_src, v_dst));
2950 return v_dst;
2953 case Iop_Clz32x4: {
2954 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2955 HReg v_dst = newVRegV(env);
2956 addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_W, v_src, v_dst));
2957 return v_dst;
2960 case Iop_Clz64x2: {
2961 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2962 HReg v_dst = newVRegV(env);
2963 addInstr(env, MIPSInstr_Msa2R(MSA_NLZC, MSA_D, v_src, v_dst));
2964 return v_dst;
2967 case Iop_Abs32Fx4: {
2968 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2969 HReg v_dst = newVRegV(env);
2970 HReg v_help = newVRegV(env);
2971 addInstr(env,
2972 MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_WH,
2973 v_help, v_src, v_src));
2974 addInstr(env,
2975 MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_WH, v_dst, v_help));
2976 return v_dst;
2979 case Iop_Abs64Fx2: {
2980 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2981 HReg v_dst = newVRegV(env);
2982 HReg v_help = newVRegV(env);
2983 addInstr(env,
2984 MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_DW,
2985 v_help, v_src, v_src));
2986 addInstr(env,
2987 MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_DW, v_dst, v_help));
2988 return v_dst;
2991 case Iop_RecipEst32Fx4: {
2992 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
2993 HReg v_dst = newVRegV(env);
2994 set_guest_MIPS_rounding_mode_MSA(env);
2995 addInstr(env,
2996 MIPSInstr_Msa2RF(MSA_FRCP, MSA_F_WH, v_dst, v_src));
2997 set_MIPS_rounding_default_MSA(env);
2998 return v_dst;
3001 case Iop_RecipEst64Fx2: {
3002 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3003 HReg v_dst = newVRegV(env);
3004 set_guest_MIPS_rounding_mode_MSA(env);
3005 addInstr(env,
3006 MIPSInstr_Msa2RF(MSA_FRCP, MSA_F_DW, v_dst, v_src));
3007 set_MIPS_rounding_default_MSA(env);
3008 return v_dst;
3011 case Iop_RSqrtEst32Fx4: {
3012 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3013 HReg v_dst = newVRegV(env);
3014 set_guest_MIPS_rounding_mode_MSA(env);
3015 addInstr(env,
3016 MIPSInstr_Msa2RF(MSA_FRSQRT, MSA_F_WH, v_dst, v_src));
3017 set_MIPS_rounding_default_MSA(env);
3018 return v_dst;
3021 case Iop_RSqrtEst64Fx2: {
3022 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3023 HReg v_dst = newVRegV(env);
3024 set_guest_MIPS_rounding_mode_MSA(env);
3025 addInstr(env,
3026 MIPSInstr_Msa2RF(MSA_FRSQRT, MSA_F_DW, v_dst, v_src));
3027 set_MIPS_rounding_default_MSA(env);
3028 return v_dst;
3031 case Iop_F16toF32x4: {
3032 HReg v_dst = newVRegV(env);
3034 if (mode64) {
3035 HReg r_src;
3036 r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3037 addInstr(env,
3038 MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src, v_dst));
3039 addInstr(env,
3040 MIPSInstr_MsaElm(MSA_INSERT, r_src, v_dst,
3041 MSA_DFN_D | 1));
3042 } else {
3043 HReg r_srch, r_srcl;
3044 iselInt64Expr(&r_srch, &r_srcl, env, e->Iex.Unop.arg);
3045 addInstr(env,
3046 MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_srcl, v_dst));
3047 addInstr(env,
3048 MIPSInstr_MsaElm(MSA_INSERT, r_srch, v_dst,
3049 MSA_DFN_W | 1));
3050 addInstr(env,
3051 MIPSInstr_MsaElm(MSA_INSERT, r_srcl, v_dst,
3052 MSA_DFN_W | 2));
3053 addInstr(env,
3054 MIPSInstr_MsaElm(MSA_INSERT, r_srch, v_dst,
3055 MSA_DFN_W | 3));
3058 addInstr(env,
3059 MIPSInstr_Msa2RF(MSA_FEXUPR, MSA_F_WH, v_dst, v_dst));
3060 return v_dst;
3063 case Iop_I32UtoF32x4_DEP: {
3064 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3065 HReg v_dst = newVRegV(env);
3066 set_guest_MIPS_rounding_mode_MSA(env);
3067 addInstr(env,
3068 MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_WH, v_dst, v_src));
3069 set_MIPS_rounding_default_MSA(env);
3070 return v_dst;
3073 case Iop_F32toI32Sx4_RZ: {
3074 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3075 HReg v_dst = newVRegV(env);
3076 addInstr(env,
3077 MIPSInstr_Msa2RF(MSA_FTRUNC_S, MSA_F_WH, v_dst, v_src));
3078 return v_dst;
3081 case Iop_F32toI32Ux4_RZ: {
3082 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3083 HReg v_dst = newVRegV(env);
3084 addInstr(env,
3085 MIPSInstr_Msa2RF(MSA_FTRUNC_U, MSA_F_WH, v_dst, v_src));
3086 return v_dst;
3089 case Iop_Log2_32Fx4: {
3090 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3091 HReg v_dst = newVRegV(env);
3092 addInstr(env,
3093 MIPSInstr_Msa2RF(MSA_FLOG2, MSA_F_WH, v_dst, v_src));
3094 return v_dst;
3097 case Iop_Log2_64Fx2: {
3098 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3099 HReg v_dst = newVRegV(env);
3100 addInstr(env,
3101 MIPSInstr_Msa2RF(MSA_FLOG2, MSA_F_DW, v_dst, v_src));
3102 return v_dst;
3104 case Iop_CmpNEZ8x16: {
3105 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3106 HReg v_dst = newVRegV(env);
3107 HReg zero = Zero(mode64);
3108 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3109 addInstr(env,
3110 MIPSInstr_Msa3R(MSA_CEQ, MSA_B, v_dst, v_src, v_dst));
3111 addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3112 return v_dst;
3114 case Iop_CmpNEZ16x8: {
3115 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3116 HReg v_dst = newVRegV(env);
3117 HReg zero = Zero(mode64);
3118 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3119 addInstr(env,
3120 MIPSInstr_Msa3R(MSA_CEQ, MSA_H, v_dst, v_src, v_dst));
3121 addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3122 return v_dst;
3124 case Iop_CmpNEZ32x4: {
3125 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3126 HReg v_dst = newVRegV(env);
3127 HReg zero = Zero(mode64);
3128 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3129 addInstr(env,
3130 MIPSInstr_Msa3R(MSA_CEQ, MSA_W, v_dst, v_src, v_dst));
3131 addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3132 return v_dst;
3134 case Iop_CmpNEZ64x2: {
3135 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
3136 HReg v_dst = newVRegV(env);
3137 HReg zero = Zero(mode64);
3138 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
3139 addInstr(env,
3140 MIPSInstr_Msa3R(MSA_CEQ, MSA_D, v_dst, v_src, v_dst));
3141 addInstr(env, MIPSInstr_MsaVec(MSA_NORV, v_dst, v_dst, v_dst));
3142 return v_dst;
3144 default:
3145 vex_printf("iselV128Expr_wrk: Unsupported unop: %u\n", op_unop);
3149 if (e->tag == Iex_Binop) {
3150 IROp op_binop = e->Iex.Binop.op;
3152 switch (op_binop) {
3153 case Iop_Add8x16: {
3154 HReg v_dst = newVRegV(env);
3155 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3156 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3157 addInstr(env,
3158 MIPSInstr_Msa3R(MSA_ADDV, MSA_B,
3159 v_dst, v_src1, v_src2));
3160 return v_dst;
3163 case Iop_Add16x8: {
3164 HReg v_dst = newVRegV(env);
3165 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3166 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3167 addInstr(env,
3168 MIPSInstr_Msa3R(MSA_ADDV, MSA_H,
3169 v_dst, v_src1, v_src2));
3170 return v_dst;
3173 case Iop_Add32x4: {
3174 HReg v_dst = newVRegV(env);
3175 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3176 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3177 addInstr(env,
3178 MIPSInstr_Msa3R(MSA_ADDV, MSA_W,
3179 v_dst, v_src1, v_src2));
3180 return v_dst;
3183 case Iop_Add64x2: {
3184 HReg v_dst = newVRegV(env);
3185 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3186 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3187 addInstr(env,
3188 MIPSInstr_Msa3R(MSA_ADDV, MSA_D,
3189 v_dst, v_src1, v_src2));
3190 return v_dst;
3193 case Iop_Sub8x16: {
3194 HReg v_dst = newVRegV(env);
3195 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3196 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3197 addInstr(env,
3198 MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
3199 v_dst, v_src1, v_src2));
3200 return v_dst;
3203 case Iop_Sub16x8: {
3204 HReg v_dst = newVRegV(env);
3205 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3206 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3207 addInstr(env,
3208 MIPSInstr_Msa3R(MSA_SUBV, MSA_H,
3209 v_dst, v_src1, v_src2));
3210 return v_dst;
3213 case Iop_Sub32x4: {
3214 HReg v_dst = newVRegV(env);
3215 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3216 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3217 addInstr(env,
3218 MIPSInstr_Msa3R(MSA_SUBV, MSA_W,
3219 v_dst, v_src1, v_src2));
3220 return v_dst;
3223 case Iop_Sub64x2: {
3224 HReg v_dst = newVRegV(env);
3225 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3226 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3227 addInstr(env,
3228 MIPSInstr_Msa3R(MSA_SUBV, MSA_D,
3229 v_dst, v_src1, v_src2));
3230 return v_dst;
3233 case Iop_QAdd8Sx16: {
3234 HReg v_dst = newVRegV(env);
3235 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3236 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3237 addInstr(env,
3238 MIPSInstr_Msa3R(MSA_ADDS_S, MSA_B,
3239 v_dst, v_src1, v_src2));
3240 return v_dst;
3243 case Iop_QAdd16Sx8: {
3244 HReg v_dst = newVRegV(env);
3245 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3246 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3247 addInstr(env,
3248 MIPSInstr_Msa3R(MSA_ADDS_S, MSA_H,
3249 v_dst, v_src1, v_src2));
3250 return v_dst;
3253 case Iop_QAdd32Sx4: {
3254 HReg v_dst = newVRegV(env);
3255 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3256 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3257 addInstr(env,
3258 MIPSInstr_Msa3R(MSA_ADDS_S, MSA_W,
3259 v_dst, v_src1, v_src2));
3260 return v_dst;
3263 case Iop_QAdd64Sx2: {
3264 HReg v_dst = newVRegV(env);
3265 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3266 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3267 addInstr(env,
3268 MIPSInstr_Msa3R(MSA_ADDS_S, MSA_D,
3269 v_dst, v_src1, v_src2));
3270 return v_dst;
3273 case Iop_QAdd8Ux16: {
3274 HReg v_dst = newVRegV(env);
3275 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3276 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3277 addInstr(env,
3278 MIPSInstr_Msa3R(MSA_ADDS_U, MSA_B,
3279 v_dst, v_src1, v_src2));
3280 return v_dst;
3283 case Iop_QAdd16Ux8: {
3284 HReg v_dst = newVRegV(env);
3285 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3286 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3287 addInstr(env,
3288 MIPSInstr_Msa3R(MSA_ADDS_U, MSA_H,
3289 v_dst, v_src1, v_src2));
3290 return v_dst;
3293 case Iop_QAdd32Ux4: {
3294 HReg v_dst = newVRegV(env);
3295 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3296 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3297 addInstr(env,
3298 MIPSInstr_Msa3R(MSA_ADDS_U, MSA_W,
3299 v_dst, v_src1, v_src2));
3300 return v_dst;
3303 case Iop_QAdd64Ux2: {
3304 HReg v_dst = newVRegV(env);
3305 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3306 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3307 addInstr(env,
3308 MIPSInstr_Msa3R(MSA_ADDS_U, MSA_D,
3309 v_dst, v_src1, v_src2));
3310 return v_dst;
3313 case Iop_QSub8Sx16: {
3314 HReg v_dst = newVRegV(env);
3315 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3316 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3317 addInstr(env,
3318 MIPSInstr_Msa3R(MSA_SUBS_S, MSA_B,
3319 v_dst, v_src1, v_src2));
3320 return v_dst;
3323 case Iop_QSub16Sx8: {
3324 HReg v_dst = newVRegV(env);
3325 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3326 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3327 addInstr(env,
3328 MIPSInstr_Msa3R(MSA_SUBS_S, MSA_H,
3329 v_dst, v_src1, v_src2));
3330 return v_dst;
3333 case Iop_QSub32Sx4: {
3334 HReg v_dst = newVRegV(env);
3335 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3336 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3337 addInstr(env,
3338 MIPSInstr_Msa3R(MSA_SUBS_S, MSA_W,
3339 v_dst, v_src1, v_src2));
3340 return v_dst;
3343 case Iop_QSub64Sx2: {
3344 HReg v_dst = newVRegV(env);
3345 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3346 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3347 addInstr(env,
3348 MIPSInstr_Msa3R(MSA_SUBS_S, MSA_D,
3349 v_dst, v_src1, v_src2));
3350 return v_dst;
3353 case Iop_QSub8Ux16: {
3354 HReg v_dst = newVRegV(env);
3355 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3356 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3357 addInstr(env,
3358 MIPSInstr_Msa3R(MSA_SUBS_U, MSA_B,
3359 v_dst, v_src1, v_src2));
3360 return v_dst;
3363 case Iop_QSub16Ux8: {
3364 HReg v_dst = newVRegV(env);
3365 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3366 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3367 addInstr(env,
3368 MIPSInstr_Msa3R(MSA_SUBS_U, MSA_H,
3369 v_dst, v_src1, v_src2));
3370 return v_dst;
3373 case Iop_QSub32Ux4: {
3374 HReg v_dst = newVRegV(env);
3375 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3376 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3377 addInstr(env,
3378 MIPSInstr_Msa3R(MSA_SUBS_U, MSA_W,
3379 v_dst, v_src1, v_src2));
3380 return v_dst;
3383 case Iop_QSub64Ux2: {
3384 HReg v_dst = newVRegV(env);
3385 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3386 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3387 addInstr(env,
3388 MIPSInstr_Msa3R(MSA_SUBS_U, MSA_D,
3389 v_dst, v_src1, v_src2));
3390 return v_dst;
3393 case Iop_QDMulHi32Sx4: {
3394 HReg v_dst = newVRegV(env);
3395 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3396 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3397 addInstr(env,
3398 MIPSInstr_Msa3RF(MSA_MUL_Q, MSA_F_DW,
3399 v_dst, v_src1, v_src2));
3400 return v_dst;
3403 case Iop_QDMulHi16Sx8: {
3404 HReg v_dst = newVRegV(env);
3405 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3406 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3407 addInstr(env,
3408 MIPSInstr_Msa3RF(MSA_MUL_Q, MSA_F_WH,
3409 v_dst, v_src1, v_src2));
3410 return v_dst;
3413 case Iop_QRDMulHi32Sx4: {
3414 HReg v_dst = newVRegV(env);
3415 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3416 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3417 addInstr(env,
3418 MIPSInstr_Msa3RF(MSA_MULR_Q, MSA_F_DW,
3419 v_dst, v_src1, v_src2));
3420 return v_dst;
3423 case Iop_QRDMulHi16Sx8: {
3424 HReg v_dst = newVRegV(env);
3425 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3426 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3427 addInstr(env,
3428 MIPSInstr_Msa3RF(MSA_MULR_Q, MSA_F_WH,
3429 v_dst, v_src1, v_src2));
3430 return v_dst;
3433 case Iop_Max8Sx16: {
3434 HReg v_dst = newVRegV(env);
3435 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3436 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3437 addInstr(env,
3438 MIPSInstr_Msa3R(MSA_MAX_S, MSA_B,
3439 v_dst, v_src1, v_src2));
3440 return v_dst;
3443 case Iop_Max16Sx8: {
3444 HReg v_dst = newVRegV(env);
3445 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3446 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3447 addInstr(env,
3448 MIPSInstr_Msa3R(MSA_MAX_S, MSA_H,
3449 v_dst, v_src1, v_src2));
3450 return v_dst;
3453 case Iop_Max32Sx4: {
3454 HReg v_dst = newVRegV(env);
3455 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3456 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3457 addInstr(env,
3458 MIPSInstr_Msa3R(MSA_MAX_S, MSA_W,
3459 v_dst, v_src1, v_src2));
3460 return v_dst;
3463 case Iop_Max64Sx2: {
3464 HReg v_dst = newVRegV(env);
3465 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3466 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3467 addInstr(env,
3468 MIPSInstr_Msa3R(MSA_MAX_S, MSA_D,
3469 v_dst, v_src1, v_src2));
3470 return v_dst;
3473 case Iop_Max8Ux16: {
3474 HReg v_dst = newVRegV(env);
3475 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3476 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3477 addInstr(env,
3478 MIPSInstr_Msa3R(MSA_MAX_U, MSA_B,
3479 v_dst, v_src1, v_src2));
3480 return v_dst;
3483 case Iop_Max16Ux8: {
3484 HReg v_dst = newVRegV(env);
3485 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3486 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3487 addInstr(env,
3488 MIPSInstr_Msa3R(MSA_MAX_U, MSA_H,
3489 v_dst, v_src1, v_src2));
3490 return v_dst;
3493 case Iop_Max32Ux4: {
3494 HReg v_dst = newVRegV(env);
3495 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3496 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3497 addInstr(env,
3498 MIPSInstr_Msa3R(MSA_MAX_U, MSA_W,
3499 v_dst, v_src1, v_src2));
3500 return v_dst;
3503 case Iop_Max64Ux2: {
3504 HReg v_dst = newVRegV(env);
3505 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3506 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3507 addInstr(env,
3508 MIPSInstr_Msa3R(MSA_MAX_U, MSA_D,
3509 v_dst, v_src1, v_src2));
3510 return v_dst;
3513 case Iop_Min8Sx16: {
3514 HReg v_dst = newVRegV(env);
3515 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3516 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3517 addInstr(env,
3518 MIPSInstr_Msa3R(MSA_MIN_S, MSA_B,
3519 v_dst, v_src1, v_src2));
3520 return v_dst;
3523 case Iop_Min16Sx8: {
3524 HReg v_dst = newVRegV(env);
3525 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3526 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3527 addInstr(env,
3528 MIPSInstr_Msa3R(MSA_MIN_S, MSA_H,
3529 v_dst, v_src1, v_src2));
3530 return v_dst;
3533 case Iop_Min32Sx4: {
3534 HReg v_dst = newVRegV(env);
3535 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3536 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3537 addInstr(env,
3538 MIPSInstr_Msa3R(MSA_MIN_S, MSA_W,
3539 v_dst, v_src1, v_src2));
3540 return v_dst;
3543 case Iop_Min64Sx2: {
3544 HReg v_dst = newVRegV(env);
3545 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3546 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3547 addInstr(env,
3548 MIPSInstr_Msa3R(MSA_MIN_S, MSA_D,
3549 v_dst, v_src1, v_src2));
3550 return v_dst;
3553 case Iop_Min8Ux16: {
3554 HReg v_dst = newVRegV(env);
3555 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3556 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3557 addInstr(env,
3558 MIPSInstr_Msa3R(MSA_MIN_U, MSA_B,
3559 v_dst, v_src1, v_src2));
3560 return v_dst;
3563 case Iop_Min16Ux8: {
3564 HReg v_dst = newVRegV(env);
3565 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3566 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3567 addInstr(env,
3568 MIPSInstr_Msa3R(MSA_MIN_U, MSA_H,
3569 v_dst, v_src1, v_src2));
3570 return v_dst;
3573 case Iop_Min32Ux4: {
3574 HReg v_dst = newVRegV(env);
3575 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3576 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3577 addInstr(env,
3578 MIPSInstr_Msa3R(MSA_MIN_U, MSA_W,
3579 v_dst, v_src1, v_src2));
3580 return v_dst;
3583 case Iop_Min64Ux2: {
3584 HReg v_dst = newVRegV(env);
3585 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3586 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3587 addInstr(env,
3588 MIPSInstr_Msa3R(MSA_MIN_U, MSA_D,
3589 v_dst, v_src1, v_src2));
3590 return v_dst;
3593 case Iop_Shl8x16: {
3594 HReg v_dst = newVRegV(env);
3595 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3596 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3597 addInstr(env,
3598 MIPSInstr_Msa3R(MSA_SLL, MSA_B, v_dst, v_src1, v_src2));
3599 return v_dst;
3602 case Iop_Shl16x8: {
3603 HReg v_dst = newVRegV(env);
3604 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3605 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3606 addInstr(env,
3607 MIPSInstr_Msa3R(MSA_SLL, MSA_H, v_dst, v_src1, v_src2));
3608 return v_dst;
3611 case Iop_Shl32x4: {
3612 HReg v_dst = newVRegV(env);
3613 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3614 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3615 addInstr(env,
3616 MIPSInstr_Msa3R(MSA_SLL, MSA_W, v_dst, v_src1, v_src2));
3617 return v_dst;
3620 case Iop_Shl64x2: {
3621 HReg v_dst = newVRegV(env);
3622 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3623 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3624 addInstr(env,
3625 MIPSInstr_Msa3R(MSA_SLL, MSA_D, v_dst, v_src1, v_src2));
3626 return v_dst;
3629 case Iop_Shr8x16: {
3630 HReg v_dst = newVRegV(env);
3631 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3632 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3633 addInstr(env,
3634 MIPSInstr_Msa3R(MSA_SRL, MSA_B, v_dst, v_src1, v_src2));
3635 return v_dst;
3638 case Iop_Shr16x8: {
3639 HReg v_dst = newVRegV(env);
3640 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3641 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3642 addInstr(env,
3643 MIPSInstr_Msa3R(MSA_SRL, MSA_H, v_dst, v_src1, v_src2));
3644 return v_dst;
3647 case Iop_Shr32x4: {
3648 HReg v_dst = newVRegV(env);
3649 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3650 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3651 addInstr(env,
3652 MIPSInstr_Msa3R(MSA_SRL, MSA_W, v_dst, v_src1, v_src2));
3653 return v_dst;
3656 case Iop_Shr64x2: {
3657 HReg v_dst = newVRegV(env);
3658 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3659 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3660 addInstr(env,
3661 MIPSInstr_Msa3R(MSA_SRL, MSA_D, v_dst, v_src1, v_src2));
3662 return v_dst;
3665 case Iop_Sar8x16: {
3666 HReg v_dst = newVRegV(env);
3667 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3668 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3669 addInstr(env,
3670 MIPSInstr_Msa3R(MSA_SRA, MSA_B, v_dst, v_src1, v_src2));
3671 return v_dst;
3674 case Iop_Sar16x8: {
3675 HReg v_dst = newVRegV(env);
3676 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3677 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3678 addInstr(env,
3679 MIPSInstr_Msa3R(MSA_SRA, MSA_H, v_dst, v_src1, v_src2));
3680 return v_dst;
3683 case Iop_Sar32x4: {
3684 HReg v_dst = newVRegV(env);
3685 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3686 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3687 addInstr(env,
3688 MIPSInstr_Msa3R(MSA_SRA, MSA_W, v_dst, v_src1, v_src2));
3689 return v_dst;
3692 case Iop_Sar64x2: {
3693 HReg v_dst = newVRegV(env);
3694 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3695 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3696 addInstr(env,
3697 MIPSInstr_Msa3R(MSA_SRA, MSA_D, v_dst, v_src1, v_src2));
3698 return v_dst;
3701 case Iop_InterleaveHI8x16: {
3702 HReg v_dst = newVRegV(env);
3703 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3704 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3705 addInstr(env,
3706 MIPSInstr_Msa3R(MSA_ILVL, MSA_B, v_dst, v_src1, v_src2));
3707 return v_dst;
3710 case Iop_InterleaveHI16x8: {
3711 HReg v_dst = newVRegV(env);
3712 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3713 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3714 addInstr(env,
3715 MIPSInstr_Msa3R(MSA_ILVL, MSA_H,
3716 v_dst, v_src1, v_src2));
3717 return v_dst;
3720 case Iop_InterleaveHI32x4: {
3721 HReg v_dst = newVRegV(env);
3722 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3723 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3724 addInstr(env,
3725 MIPSInstr_Msa3R(MSA_ILVL, MSA_W,
3726 v_dst, v_src1, v_src2));
3727 return v_dst;
3730 case Iop_InterleaveHI64x2: {
3731 HReg v_dst = newVRegV(env);
3732 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3733 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3734 addInstr(env,
3735 MIPSInstr_Msa3R(MSA_ILVL, MSA_D,
3736 v_dst, v_src1, v_src2));
3737 return v_dst;
3740 case Iop_InterleaveLO8x16: {
3741 HReg v_dst = newVRegV(env);
3742 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3743 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3744 addInstr(env,
3745 MIPSInstr_Msa3R(MSA_ILVR, MSA_B,
3746 v_dst, v_src1, v_src2));
3747 return v_dst;
3750 case Iop_InterleaveLO16x8: {
3751 HReg v_dst = newVRegV(env);
3752 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3753 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3754 addInstr(env,
3755 MIPSInstr_Msa3R(MSA_ILVR, MSA_H,
3756 v_dst, v_src1, v_src2));
3757 return v_dst;
3760 case Iop_InterleaveLO32x4: {
3761 HReg v_dst = newVRegV(env);
3762 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3763 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3764 addInstr(env,
3765 MIPSInstr_Msa3R(MSA_ILVR, MSA_W,
3766 v_dst, v_src1, v_src2));
3767 return v_dst;
3770 case Iop_InterleaveLO64x2: {
3771 HReg v_dst = newVRegV(env);
3772 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3773 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3774 addInstr(env,
3775 MIPSInstr_Msa3R(MSA_ILVR, MSA_D,
3776 v_dst, v_src1, v_src2));
3777 return v_dst;
3780 case Iop_InterleaveEvenLanes8x16: {
3781 HReg v_dst = newVRegV(env);
3782 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3783 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3784 addInstr(env,
3785 MIPSInstr_Msa3R(MSA_ILVEV, MSA_B,
3786 v_dst, v_src1, v_src2));
3787 return v_dst;
3790 case Iop_InterleaveEvenLanes16x8: {
3791 HReg v_dst = newVRegV(env);
3792 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3793 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3794 addInstr(env,
3795 MIPSInstr_Msa3R(MSA_ILVEV, MSA_H,
3796 v_dst, v_src1, v_src2));
3797 return v_dst;
3800 case Iop_InterleaveEvenLanes32x4: {
3801 HReg v_dst = newVRegV(env);
3802 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3803 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3804 addInstr(env,
3805 MIPSInstr_Msa3R(MSA_ILVEV, MSA_W,
3806 v_dst, v_src1, v_src2));
3807 return v_dst;
3810 case Iop_InterleaveOddLanes8x16: {
3811 HReg v_dst = newVRegV(env);
3812 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3813 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3814 addInstr(env,
3815 MIPSInstr_Msa3R(MSA_ILVOD, MSA_B,
3816 v_dst, v_src1, v_src2));
3817 return v_dst;
3820 case Iop_InterleaveOddLanes16x8: {
3821 HReg v_dst = newVRegV(env);
3822 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3823 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3824 addInstr(env,
3825 MIPSInstr_Msa3R(MSA_ILVOD, MSA_H,
3826 v_dst, v_src1, v_src2));
3827 return v_dst;
3830 case Iop_InterleaveOddLanes32x4: {
3831 HReg v_dst = newVRegV(env);
3832 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3833 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3834 addInstr(env,
3835 MIPSInstr_Msa3R(MSA_ILVOD, MSA_W,
3836 v_dst, v_src1, v_src2));
3837 return v_dst;
3840 case Iop_PackEvenLanes8x16: {
3841 HReg v_dst = newVRegV(env);
3842 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3843 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3844 addInstr(env,
3845 MIPSInstr_Msa3R(MSA_PCKEV, MSA_B,
3846 v_dst, v_src1, v_src2));
3847 return v_dst;
3850 case Iop_PackEvenLanes16x8: {
3851 HReg v_dst = newVRegV(env);
3852 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3853 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3854 addInstr(env,
3855 MIPSInstr_Msa3R(MSA_PCKEV, MSA_H,
3856 v_dst, v_src1, v_src2));
3857 return v_dst;
3860 case Iop_PackEvenLanes32x4: {
3861 HReg v_dst = newVRegV(env);
3862 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3863 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3864 addInstr(env,
3865 MIPSInstr_Msa3R(MSA_PCKEV, MSA_W,
3866 v_dst, v_src1, v_src2));
3867 return v_dst;
3870 case Iop_PackOddLanes8x16: {
3871 HReg v_dst = newVRegV(env);
3872 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3873 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3874 addInstr(env,
3875 MIPSInstr_Msa3R(MSA_PCKOD, MSA_B,
3876 v_dst, v_src1, v_src2));
3877 return v_dst;
3880 case Iop_PackOddLanes16x8: {
3881 HReg v_dst = newVRegV(env);
3882 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3883 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3884 addInstr(env,
3885 MIPSInstr_Msa3R(MSA_PCKOD, MSA_H,
3886 v_dst, v_src1, v_src2));
3887 return v_dst;
3890 case Iop_PackOddLanes32x4: {
3891 HReg v_dst = newVRegV(env);
3892 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3893 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3894 addInstr(env,
3895 MIPSInstr_Msa3R(MSA_PCKOD, MSA_W,
3896 v_dst, v_src1, v_src2));
3897 return v_dst;
3900 case Iop_CmpEQ8x16: {
3901 HReg v_dst = newVRegV(env);
3902 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3903 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3904 addInstr(env,
3905 MIPSInstr_Msa3R(MSA_CEQ, MSA_B, v_dst, v_src1, v_src2));
3906 return v_dst;
3909 case Iop_CmpEQ16x8: {
3910 HReg v_dst = newVRegV(env);
3911 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3912 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3913 addInstr(env,
3914 MIPSInstr_Msa3R(MSA_CEQ, MSA_H, v_dst, v_src1, v_src2));
3915 return v_dst;
3918 case Iop_CmpEQ32x4: {
3919 HReg v_dst = newVRegV(env);
3920 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3921 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3922 addInstr(env,
3923 MIPSInstr_Msa3R(MSA_CEQ, MSA_W, v_dst, v_src1, v_src2));
3924 return v_dst;
3927 case Iop_CmpEQ64x2: {
3928 HReg v_dst = newVRegV(env);
3929 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3930 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3931 addInstr(env,
3932 MIPSInstr_Msa3R(MSA_CEQ, MSA_D, v_dst, v_src1, v_src2));
3933 return v_dst;
3936 case Iop_CmpGT8Sx16: {
3937 HReg v_dst = newVRegV(env);
3938 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3939 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3940 addInstr(env,
3941 MIPSInstr_Msa3R(MSA_CLT_S, MSA_B,
3942 v_dst, v_src2, v_src1));
3943 return v_dst;
3946 case Iop_CmpGT16Sx8: {
3947 HReg v_dst = newVRegV(env);
3948 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3949 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3950 addInstr(env,
3951 MIPSInstr_Msa3R(MSA_CLT_S, MSA_H,
3952 v_dst, v_src2, v_src1));
3953 return v_dst;
3956 case Iop_CmpGT32Sx4: {
3957 HReg v_dst = newVRegV(env);
3958 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3959 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3960 addInstr(env,
3961 MIPSInstr_Msa3R(MSA_CLT_S, MSA_W,
3962 v_dst, v_src2, v_src1));
3963 return v_dst;
3966 case Iop_CmpGT64Sx2: {
3967 HReg v_dst = newVRegV(env);
3968 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3969 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3970 addInstr(env,
3971 MIPSInstr_Msa3R(MSA_CLT_S, MSA_D,
3972 v_dst, v_src2, v_src1));
3973 return v_dst;
3976 case Iop_CmpGT8Ux16: {
3977 HReg v_dst = newVRegV(env);
3978 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3979 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3980 addInstr(env,
3981 MIPSInstr_Msa3R(MSA_CLT_U, MSA_B,
3982 v_dst, v_src2, v_src1));
3983 return v_dst;
3986 case Iop_CmpGT16Ux8: {
3987 HReg v_dst = newVRegV(env);
3988 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3989 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
3990 addInstr(env,
3991 MIPSInstr_Msa3R(MSA_CLT_U, MSA_H,
3992 v_dst, v_src2, v_src1));
3993 return v_dst;
3996 case Iop_CmpGT32Ux4: {
3997 HReg v_dst = newVRegV(env);
3998 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
3999 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4000 addInstr(env,
4001 MIPSInstr_Msa3R(MSA_CLT_U, MSA_W,
4002 v_dst, v_src2, v_src1));
4003 return v_dst;
4006 case Iop_CmpGT64Ux2: {
4007 HReg v_dst = newVRegV(env);
4008 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4009 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4010 addInstr(env,
4011 MIPSInstr_Msa3R(MSA_CLT_U, MSA_D,
4012 v_dst, v_src2, v_src1));
4013 return v_dst;
4016 case Iop_Avg8Sx16: {
4017 HReg v_dst = newVRegV(env);
4018 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4019 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4020 addInstr(env,
4021 MIPSInstr_Msa3R(MSA_AVER_S, MSA_B,
4022 v_dst, v_src1, v_src2));
4023 return v_dst;
4026 case Iop_Avg16Sx8: {
4027 HReg v_dst = newVRegV(env);
4028 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4029 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4030 addInstr(env,
4031 MIPSInstr_Msa3R(MSA_AVER_S, MSA_H,
4032 v_dst, v_src1, v_src2));
4033 return v_dst;
4036 case Iop_Avg32Sx4: {
4037 HReg v_dst = newVRegV(env);
4038 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4039 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4040 addInstr(env,
4041 MIPSInstr_Msa3R(MSA_AVER_S, MSA_W,
4042 v_dst, v_src1, v_src2));
4043 return v_dst;
4046 case Iop_Avg8Ux16: {
4047 HReg v_dst = newVRegV(env);
4048 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4049 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4050 addInstr(env,
4051 MIPSInstr_Msa3R(MSA_AVER_U, MSA_B,
4052 v_dst, v_src1, v_src2));
4053 return v_dst;
4056 case Iop_Avg16Ux8: {
4057 HReg v_dst = newVRegV(env);
4058 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4059 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4060 addInstr(env,
4061 MIPSInstr_Msa3R(MSA_AVER_U, MSA_H,
4062 v_dst, v_src1, v_src2));
4063 return v_dst;
4066 case Iop_Avg32Ux4: {
4067 HReg v_dst = newVRegV(env);
4068 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4069 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4070 addInstr(env,
4071 MIPSInstr_Msa3R(MSA_AVER_U, MSA_W,
4072 v_dst, v_src1, v_src2));
4073 return v_dst;
4076 case Iop_Mul8x16: {
4077 HReg v_dst = newVRegV(env);
4078 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4079 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4080 addInstr(env,
4081 MIPSInstr_Msa3R(MSA_MULV, MSA_B,
4082 v_dst, v_src1, v_src2));
4083 return v_dst;
4086 case Iop_Mul16x8: {
4087 HReg v_dst = newVRegV(env);
4088 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4089 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4090 addInstr(env,
4091 MIPSInstr_Msa3R(MSA_MULV, MSA_H,
4092 v_dst, v_src1, v_src2));
4093 return v_dst;
4096 case Iop_Mul32x4: {
4097 HReg v_dst = newVRegV(env);
4098 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4099 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4100 addInstr(env,
4101 MIPSInstr_Msa3R(MSA_MULV, MSA_W,
4102 v_dst, v_src1, v_src2));
4103 return v_dst;
4106 case Iop_AndV128: {
4107 HReg v_dst = newVRegV(env);
4108 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4109 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4110 addInstr(env, MIPSInstr_MsaVec(MSA_ANDV, v_dst, v_src1, v_src2));
4111 return v_dst;
4114 case Iop_OrV128: {
4115 HReg v_dst = newVRegV(env);
4116 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4117 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4118 addInstr(env, MIPSInstr_MsaVec(MSA_ORV, v_dst, v_src1, v_src2));
4119 return v_dst;
4122 case Iop_XorV128: {
4123 HReg v_dst = newVRegV(env);
4124 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4125 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4126 addInstr(env, MIPSInstr_MsaVec(MSA_XORV, v_dst, v_src1, v_src2));
4127 return v_dst;
4130 case Iop_ShrV128: {
4131 HReg v_dst = newVRegV(env);
4132 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4133 MIPSRH *sm;
4134 sm = iselWordExpr_RH7u(env, e->Iex.Binop.arg2);
4135 addInstr(env,
4136 MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
4137 v_dst, v_src1, v_src1));
4139 if (sm->tag == Mrh_Imm) {
4140 int n = (sm->Mrh.Imm.imm16) >> 3;
4141 addInstr(env,
4142 MIPSInstr_MsaElm(MSA_SLDI, v_src1, v_dst,
4143 MSA_DFN_B | n));
4144 } else {
4145 HReg v_src2 = sm->Mrh.Reg.reg;
4146 MIPSRH *ri = MIPSRH_Imm(False, 3);
4147 HReg r_dst = newVRegI(env);
4148 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
4149 r_dst, v_src2, ri));
4150 addInstr(env,
4151 MIPSInstr_Msa3R(MSA_SLD, MSA_B,
4152 v_dst, v_src1, r_dst));
4155 return v_dst;
4158 case Iop_ShlV128: {
4159 HReg v_dst = newVRegV(env);
4160 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4161 MIPSRH *sm;
4162 sm = iselWordExpr_RH7u(env, e->Iex.Binop.arg2);
4163 addInstr(env,
4164 MIPSInstr_Msa3R(MSA_SUBV, MSA_B,
4165 v_dst, v_src1, v_src1));
4167 if (sm->tag == Mrh_Imm) {
4168 int n = 16 - ((sm->Mrh.Imm.imm16) >> 3);
4170 if (n == 16) n = 0;
4172 addInstr(env,
4173 MIPSInstr_MsaElm(MSA_SLDI, v_dst, v_src1,
4174 MSA_DFN_B | n));
4175 } else {
4176 HReg v_src2 = sm->Mrh.Reg.reg;
4177 MIPSRH *ri = MIPSRH_Imm(False, 3);
4178 HReg r_dst = newVRegI(env);
4179 HReg help = newVRegI(env);
4180 addInstr(env, MIPSInstr_Alu(Malu_XOR, help, v_src2, sm));
4181 addInstr(env, MIPSInstr_Alu(Malu_SUB, help, help, sm));
4182 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /*32bit shift */,
4183 r_dst, help, ri));
4184 addInstr(env,
4185 MIPSInstr_Msa3R(MSA_SLD, MSA_B,
4186 v_src1, v_dst, r_dst));
4189 return v_src1;
4192 case Iop_ShlN8x16: {
4193 HReg v_dst = newVRegV(env);
4194 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4195 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4196 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4197 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4198 addInstr(env,
4199 MIPSInstr_MsaBit(MSA_SLLI, MSA_B,
4200 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4201 v_src1, v_dst));
4202 return v_dst;
4205 case Iop_ShlN16x8: {
4206 HReg v_dst = newVRegV(env);
4207 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4208 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4209 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4210 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4211 addInstr(env,
4212 MIPSInstr_MsaBit(MSA_SLLI, MSA_H,
4213 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4214 v_src1, v_dst));
4215 return v_dst;
4218 case Iop_ShlN32x4: {
4219 HReg v_dst = newVRegV(env);
4220 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4221 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4222 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4223 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4224 addInstr(env,
4225 MIPSInstr_MsaBit(MSA_SLLI, MSA_W,
4226 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4227 v_src1, v_dst));
4228 return v_dst;
4231 case Iop_ShlN64x2: {
4232 HReg v_dst = newVRegV(env);
4233 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4234 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4235 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4236 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4237 addInstr(env,
4238 MIPSInstr_MsaBit(MSA_SLLI, MSA_D,
4239 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4240 v_src1, v_dst));
4241 return v_dst;
4244 case Iop_SarN8x16: {
4245 HReg v_dst = newVRegV(env);
4246 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4247 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4248 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4249 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4250 addInstr(env,
4251 MIPSInstr_MsaBit(MSA_SRAI, MSA_B,
4252 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4253 v_src1, v_dst));
4254 return v_dst;
4257 case Iop_SarN16x8: {
4258 HReg v_dst = newVRegV(env);
4259 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4260 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4261 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4262 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4263 addInstr(env,
4264 MIPSInstr_MsaBit(MSA_SRAI, MSA_H,
4265 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4266 v_src1, v_dst));
4267 return v_dst;
4270 case Iop_SarN32x4: {
4271 HReg v_dst = newVRegV(env);
4272 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4273 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4274 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4275 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4276 addInstr(env,
4277 MIPSInstr_MsaBit(MSA_SRAI, MSA_W,
4278 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4279 v_src1, v_dst));
4280 return v_dst;
4283 case Iop_SarN64x2: {
4284 HReg v_dst = newVRegV(env);
4285 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4286 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4287 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4288 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4289 addInstr(env,
4290 MIPSInstr_MsaBit(MSA_SRAI, MSA_D,
4291 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4292 v_src1, v_dst));
4293 return v_dst;
4296 case Iop_ShrN8x16: {
4297 HReg v_dst = newVRegV(env);
4298 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4299 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4300 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4301 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4302 addInstr(env,
4303 MIPSInstr_MsaBit(MSA_SRLI, MSA_B,
4304 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4305 v_src1, v_dst));
4306 return v_dst;
4309 case Iop_ShrN16x8: {
4310 HReg v_dst = newVRegV(env);
4311 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4312 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4313 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4314 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4315 addInstr(env,
4316 MIPSInstr_MsaBit(MSA_SRLI, MSA_H,
4317 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4318 v_src1, v_dst));
4319 return v_dst;
4322 case Iop_ShrN32x4: {
4323 HReg v_dst = newVRegV(env);
4324 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4325 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4326 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4327 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4328 addInstr(env,
4329 MIPSInstr_MsaBit(MSA_SRLI, MSA_W,
4330 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4331 v_src1, v_dst));
4332 return v_dst;
4335 case Iop_ShrN64x2: {
4336 HReg v_dst = newVRegV(env);
4337 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4338 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4339 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4340 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4341 addInstr(env,
4342 MIPSInstr_MsaBit(MSA_SRLI, MSA_D,
4343 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4344 v_src1, v_dst));
4345 return v_dst;
4348 case Iop_QandQSarNnarrow64Sto32Sx2: {
4349 HReg v_dst = newVRegV(env);
4350 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4351 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4352 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4353 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4354 addInstr(env,
4355 MIPSInstr_MsaBit(MSA_SRAI, MSA_D,
4356 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4357 v_src1, v_dst));
4358 addInstr(env, MIPSInstr_MsaBit(MSA_SAT_S, MSA_D, 31, v_dst, v_dst));
4359 return v_dst;
4362 case Iop_QandQSarNnarrow32Sto16Sx4: {
4363 HReg v_dst = newVRegV(env);
4364 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4365 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4366 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4367 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4368 addInstr(env,
4369 MIPSInstr_MsaBit(MSA_SRAI, MSA_W,
4370 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4371 v_src1, v_dst));
4372 addInstr(env,
4373 MIPSInstr_MsaBit(MSA_SAT_S, MSA_W, 15, v_dst, v_dst));
4374 return v_dst;
4377 case Iop_QandQRSarNnarrow64Sto32Sx2: {
4378 HReg v_dst = newVRegV(env);
4379 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4380 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4381 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4382 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4383 addInstr(env,
4384 MIPSInstr_MsaBit(MSA_SRARI, MSA_D,
4385 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4386 v_src1, v_dst));
4387 addInstr(env,
4388 MIPSInstr_MsaBit(MSA_SAT_S, MSA_D, 31, v_dst, v_dst));
4389 return v_dst;
4392 case Iop_QandQRSarNnarrow32Sto16Sx4: {
4393 HReg v_dst = newVRegV(env);
4394 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4395 vassert(e->Iex.Binop.arg2->tag == Iex_Const);
4396 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
4397 vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
4398 addInstr(env,
4399 MIPSInstr_MsaBit(MSA_SRARI, MSA_W,
4400 e->Iex.Binop.arg2->Iex.Const.con->Ico.U8,
4401 v_src1, v_dst));
4402 addInstr(env,
4403 MIPSInstr_MsaBit(MSA_SAT_S, MSA_W, 15, v_dst, v_dst));
4404 return v_dst;
4407 case Iop_CmpEQ32Fx4: {
4408 HReg v_dst = newVRegV(env);
4409 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4410 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4411 addInstr(env,
4412 MIPSInstr_Msa3RF(MSA_FCEQ, MSA_F_WH,
4413 v_dst, v_src1, v_src2));
4414 return v_dst;
4417 case Iop_CmpEQ64Fx2: {
4418 HReg v_dst = newVRegV(env);
4419 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4420 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4421 addInstr(env,
4422 MIPSInstr_Msa3RF(MSA_FCEQ, MSA_F_DW,
4423 v_dst, v_src1, v_src2));
4424 return v_dst;
4427 case Iop_CmpLT32Fx4: {
4428 HReg v_dst = newVRegV(env);
4429 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4430 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4431 addInstr(env,
4432 MIPSInstr_Msa3RF(MSA_FCLT, MSA_F_WH,
4433 v_dst, v_src1, v_src2));
4434 return v_dst;
4437 case Iop_CmpLT64Fx2: {
4438 HReg v_dst = newVRegV(env);
4439 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4440 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4441 addInstr(env,
4442 MIPSInstr_Msa3RF(MSA_FCLT, MSA_F_DW,
4443 v_dst, v_src1, v_src2));
4444 return v_dst;
4447 case Iop_CmpLE32Fx4: {
4448 HReg v_dst = newVRegV(env);
4449 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4450 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4451 addInstr(env,
4452 MIPSInstr_Msa3RF(MSA_FCLE, MSA_F_WH,
4453 v_dst, v_src1, v_src2));
4454 return v_dst;
4457 case Iop_CmpLE64Fx2: {
4458 HReg v_dst = newVRegV(env);
4459 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4460 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4461 addInstr(env,
4462 MIPSInstr_Msa3RF(MSA_FCLE, MSA_F_DW,
4463 v_dst, v_src1, v_src2));
4464 return v_dst;
4467 case Iop_CmpUN32Fx4: {
4468 HReg v_dst = newVRegV(env);
4469 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4470 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4471 addInstr(env,
4472 MIPSInstr_Msa3RF(MSA_FCUN, MSA_F_WH,
4473 v_dst, v_src1, v_src2));
4474 return v_dst;
4477 case Iop_CmpUN64Fx2: {
4478 HReg v_dst = newVRegV(env);
4479 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4480 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4481 addInstr(env,
4482 MIPSInstr_Msa3RF(MSA_FCUN, MSA_F_DW,
4483 v_dst, v_src1, v_src2));
4484 return v_dst;
4487 case Iop_64HLtoV128: {
4488 HReg v_dst = newVRegV(env);
4490 if (mode64) {
4491 HReg r_src1;
4492 HReg r_src2;
4493 r_src1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
4494 r_src2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
4495 addInstr(env,
4496 MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src2, v_dst));
4497 addInstr(env,
4498 MIPSInstr_MsaElm(MSA_INSERT, r_src1, v_dst,
4499 MSA_DFN_D | 1));
4500 } else {
4501 HReg r_src1h, r_src1l;
4502 HReg r_src2h, r_src2l;
4503 iselInt64Expr(&r_src1h, &r_src1l, env, e->Iex.Binop.arg1);
4504 iselInt64Expr(&r_src2h, &r_src2l, env, e->Iex.Binop.arg2);
4505 addInstr(env,
4506 MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_src2l, v_dst));
4507 addInstr(env,
4508 MIPSInstr_MsaElm(MSA_INSERT, r_src2h, v_dst,
4509 MSA_DFN_W | 1));
4510 addInstr(env,
4511 MIPSInstr_MsaElm(MSA_INSERT, r_src1l, v_dst,
4512 MSA_DFN_W | 2));
4513 addInstr(env,
4514 MIPSInstr_MsaElm(MSA_INSERT, r_src1h, v_dst,
4515 MSA_DFN_W | 3));
4518 return v_dst;
4521 case Iop_Min32Fx4: {
4522 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4523 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4524 HReg v_dst = newVRegV(env);
4525 addInstr(env,
4526 MIPSInstr_Msa3RF(MSA_FMIN, MSA_F_WH,
4527 v_dst, v_src1, v_src2));
4528 return v_dst;
4531 case Iop_Min64Fx2: {
4532 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4533 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4534 HReg v_dst = newVRegV(env);
4535 addInstr(env,
4536 MIPSInstr_Msa3RF(MSA_FMIN, MSA_F_DW,
4537 v_dst, v_src1, v_src2));
4538 return v_dst;
4541 case Iop_Max32Fx4: {
4542 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4543 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4544 HReg v_dst = newVRegV(env);
4545 addInstr(env,
4546 MIPSInstr_Msa3RF(MSA_FMAX, MSA_F_WH,
4547 v_dst, v_src1, v_src2));
4548 return v_dst;
4551 case Iop_Max64Fx2: {
4552 HReg v_src1 = iselV128Expr(env, e->Iex.Binop.arg1);
4553 HReg v_src2 = iselV128Expr(env, e->Iex.Binop.arg2);
4554 HReg v_dst = newVRegV(env);
4555 addInstr(env,
4556 MIPSInstr_Msa3RF(MSA_FMAX, MSA_F_DW,
4557 v_dst, v_src1, v_src2));
4558 return v_dst;
4561 case Iop_Sqrt32Fx4: {
4562 HReg v_src = iselV128Expr(env, e->Iex.Binop.arg2);
4563 HReg v_dst = newVRegV(env);
4564 set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
4565 addInstr(env,
4566 MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_WH, v_dst, v_src));
4567 set_MIPS_rounding_default_MSA(env);
4568 return v_dst;
4571 case Iop_Sqrt64Fx2: {
4572 HReg v_src = iselV128Expr(env, e->Iex.Binop.arg2);
4573 HReg v_dst = newVRegV(env);
4574 set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
4575 addInstr(env,
4576 MIPSInstr_Msa2RF(MSA_FSQRT, MSA_F_DW, v_dst, v_src));
4577 set_MIPS_rounding_default_MSA(env);
4578 return v_dst;
4581 default:
4582 vex_printf("iselV128Expr_wrk: unsupported binop: %x\n", op_binop);
4586 if (e->tag == Iex_Triop) {
4587 IROp op_triop = e->Iex.Triop.details->op;
4589 switch (op_triop) {
4590 case Iop_Add32Fx4: {
4591 HReg v_dst = newVRegV(env);
4592 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4593 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4594 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4595 addInstr(env,
4596 MIPSInstr_Msa3RF(MSA_FADD, MSA_F_WH,
4597 v_dst, v_src1, v_src2));
4598 set_MIPS_rounding_default_MSA(env);
4599 return v_dst;
4602 case Iop_Add64Fx2: {
4603 HReg v_dst = newVRegV(env);
4604 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4605 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4606 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4607 addInstr(env,
4608 MIPSInstr_Msa3RF(MSA_FADD, MSA_F_DW,
4609 v_dst, v_src1, v_src2));
4610 set_MIPS_rounding_default_MSA(env);
4611 return v_dst;
4614 case Iop_Sub32Fx4: {
4615 HReg v_dst = newVRegV(env);
4616 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4617 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4618 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4619 addInstr(env,
4620 MIPSInstr_Msa3RF(MSA_FSUB, MSA_F_WH,
4621 v_dst, v_src1, v_src2));
4622 set_MIPS_rounding_default_MSA(env);
4623 return v_dst;
4626 case Iop_Sub64Fx2: {
4627 HReg v_dst = newVRegV(env);
4628 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4629 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4630 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4631 addInstr(env,
4632 MIPSInstr_Msa3RF(MSA_FSUB, MSA_F_DW,
4633 v_dst, v_src1, v_src2));
4634 set_MIPS_rounding_default_MSA(env);
4635 return v_dst;
4638 case Iop_Mul32Fx4: {
4639 HReg v_dst = newVRegV(env);
4640 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4641 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4642 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4643 addInstr(env,
4644 MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_WH,
4645 v_dst, v_src1, v_src2));
4646 set_MIPS_rounding_default_MSA(env);
4647 return v_dst;
4650 case Iop_Mul64Fx2: {
4651 HReg v_dst = newVRegV(env);
4652 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4653 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4654 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4655 addInstr(env,
4656 MIPSInstr_Msa3RF(MSA_FMUL, MSA_F_DW,
4657 v_dst, v_src1, v_src2));
4658 set_MIPS_rounding_default_MSA(env);
4659 return v_dst;
4662 case Iop_Div32Fx4: {
4663 HReg v_dst = newVRegV(env);
4664 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4665 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4666 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4667 addInstr(env,
4668 MIPSInstr_Msa3RF(MSA_FDIV, MSA_F_WH,
4669 v_dst, v_src1, v_src2));
4670 set_MIPS_rounding_default_MSA(env);
4671 return v_dst;
4674 case Iop_Div64Fx2: {
4675 HReg v_dst = newVRegV(env);
4676 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4677 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4678 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4679 addInstr(env,
4680 MIPSInstr_Msa3RF(MSA_FDIV, MSA_F_DW,
4681 v_dst, v_src1, v_src2));
4682 set_MIPS_rounding_default_MSA(env);
4683 return v_dst;
4686 case Iop_F32x4_2toQ16x8: {
4687 HReg v_dst = newVRegV(env);
4688 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4689 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4690 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4691 addInstr(env,
4692 MIPSInstr_Msa3RF(MSA_FTQ, MSA_F_WH,
4693 v_dst, v_src1, v_src2));
4694 set_MIPS_rounding_default_MSA(env);
4695 return v_dst;
4698 case Iop_F64x2_2toQ32x4: {
4699 HReg v_dst = newVRegV(env);
4700 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4701 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4702 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4703 addInstr(env,
4704 MIPSInstr_Msa3RF(MSA_FTQ, MSA_F_DW,
4705 v_dst, v_src1, v_src2));
4706 set_MIPS_rounding_default_MSA(env);
4707 return v_dst;
4710 case Iop_Scale2_32Fx4: {
4711 HReg v_dst = newVRegV(env);
4712 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4713 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4714 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4715 addInstr(env,
4716 MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_WH,
4717 v_dst, v_src1, v_src2));
4718 set_MIPS_rounding_default_MSA(env);
4719 return v_dst;
4722 case Iop_Scale2_64Fx2: {
4723 HReg v_dst = newVRegV(env);
4724 HReg v_src1 = iselV128Expr(env, e->Iex.Triop.details->arg2);
4725 HReg v_src2 = iselV128Expr(env, e->Iex.Triop.details->arg3);
4726 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
4727 addInstr(env,
4728 MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW,
4729 v_dst, v_src1, v_src2));
4730 set_MIPS_rounding_default_MSA(env);
4731 return v_dst;
4734 default:
4735 vex_printf("iselV128Expr_wrk: unsupported triop: %x\n", op_triop);
4739 if (e->tag == Iex_Const) {
4740 IRConst *con = e->Iex.Const.con;
4742 if (con->tag != Ico_V128) {
4743 vpanic("iselV128Expr.const(mips)");
4744 } else {
4745 HReg v_dst = newVRegV(env);
4746 UShort val = con->Ico.V128;
4747 HReg zero = Zero(mode64);
4749 switch (val) {
4750 case 0: /* likely */
4751 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, zero, v_dst));
4752 break;
4754 default: {
4755 HReg r_tmp = newVRegI(env);
4756 UInt i;
4757 addInstr(env, MIPSInstr_LI(r_tmp, 0xfful));
4759 if (val & 1) {
4760 addInstr(env,
4761 MIPSInstr_Msa2R(MSA_FILL, MSA_B, r_tmp, v_dst));
4762 } else {
4763 addInstr(env,
4764 MIPSInstr_Msa2R(MSA_FILL, MSA_B, zero, v_dst));
4767 for (i = 1; i < 16; i++) {
4768 val >>= 1;
4770 if (val & 1) {
4771 addInstr(env,
4772 MIPSInstr_MsaElm(MSA_INSERT, r_tmp, v_dst,
4773 MSA_DFN_B | i));
4774 } else {
4775 addInstr(env,
4776 MIPSInstr_MsaElm(MSA_INSERT, zero, v_dst,
4777 MSA_DFN_B | i));
4781 break;
4785 return v_dst;
4789 if (e->tag == Iex_ITE) {
4790 HReg v_dst = newVRegV(env);
4791 HReg iff = iselV128Expr(env, e->Iex.ITE.iffalse);
4792 HReg ift = iselV128Expr(env, e->Iex.ITE.iftrue);
4793 HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
4794 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_cond, r_cond,
4795 MIPSRH_Imm(False, 1)));
4796 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_cond, v_dst));
4797 addInstr(env,
4798 MIPSInstr_Alu(Malu_ADD, r_cond, r_cond, MIPSRH_Imm(True, 1)));
4799 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_cond, v_dst, MSA_DFN_W | 2));
4800 addInstr(env, MIPSInstr_Msa3R(MSA_VSHF, MSA_D, v_dst, ift, iff));
4801 return v_dst;
4804 vex_printf("iselV128Expr_wrk: Unsupported tag: %x\n", e->tag);
4805 ppIRExpr(e);
4806 vpanic("iselV128Expr(mips)");
4809 /*---------------------------------------------------------*/
4810 /*--- ISEL: Integer expressions (128 bit) ---*/
4811 /*---------------------------------------------------------*/
4813 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
4814 which is returned as the first two parameters. As with
4815 iselWordExpr_R, these may be either real or virtual regs; in any
4816 case they must not be changed by subsequent code emitted by the
4817 caller. */
4819 static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4821 vassert(env->mode64);
4822 iselInt128Expr_wrk(rHi, rLo, env, e);
4823 vassert(hregClass(*rHi) == HRcGPR(env->mode64));
4824 vassert(hregIsVirtual(*rHi));
4825 vassert(hregClass(*rLo) == HRcGPR(env->mode64));
4826 vassert(hregIsVirtual(*rLo));
4829 /* DO NOT CALL THIS DIRECTLY ! */
4830 static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
4831 IRExpr * e)
4833 vassert(e);
4834 vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
4836 /* read 128-bit IRTemp */
4837 if (e->tag == Iex_RdTmp) {
4838 lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
4839 return;
4842 /* --------- BINARY ops --------- */
4843 if (e->tag == Iex_Binop) {
4844 switch (e->Iex.Binop.op) {
4845 /* 64 x 64 -> 128 multiply */
4846 case Iop_MullU64:
4847 case Iop_MullS64: {
4848 HReg tLo = newVRegI(env);
4849 HReg tHi = newVRegI(env);
4850 Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
4851 HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
4852 HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
4853 #if (__mips_isa_rev >= 6)
4854 addInstr(env, MIPSInstr_Mulr6(syned, False, True,
4855 tLo, r_srcL, r_srcR));
4856 addInstr(env, MIPSInstr_Mulr6(syned, False, False,
4857 tHi, r_srcL, r_srcR));
4858 #else
4859 addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
4860 addInstr(env, MIPSInstr_Mfhi(tHi));
4861 addInstr(env, MIPSInstr_Mflo(tLo));
4862 #endif
4863 *rHi = tHi;
4864 *rLo = tLo;
4865 return;
4868 /* 64HLto128(e1,e2) */
4869 case Iop_64HLto128:
4870 *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
4871 *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
4872 return;
4874 case Iop_DivModU64to64:
4875 case Iop_DivModS64to64: {
4876 HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
4877 HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
4878 HReg tLo = newVRegI(env);
4879 HReg tHi = newVRegI(env);
4880 Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
4881 #if (__mips_isa_rev >= 6)
4882 addInstr(env, MIPSInstr_Divr6(syned/*Unsigned or Signed */ ,
4883 False /*32bit or 64bit div */ ,
4884 False /*mod*/,
4885 tLo, r_srcL, r_srcR));
4886 addInstr(env, MIPSInstr_Divr6(syned/*Unsigned or Signed */ ,
4887 False /*32bit or 64bit div */ ,
4888 True /*mod*/,
4889 tHi, r_srcL, r_srcR));
4890 #else
4891 addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
4892 addInstr(env, MIPSInstr_Mfhi(tHi));
4893 addInstr(env, MIPSInstr_Mflo(tLo));
4894 #endif
4895 *rHi = tHi;
4896 *rLo = tLo;
4897 return;
4900 default:
4901 break;
4904 vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
4905 ppIRExpr(e);
4906 vpanic("iselInt128Expr(mips64)");
4909 /*---------------------------------------------------------*/
4910 /*--- ISEL: Integer expressions (64 bit) ---*/
4911 /*---------------------------------------------------------*/
4913 /* 32-bit mode ONLY. Compute a 64-bit value into the register
4914 * pair HI, LO. HI and LO must not be changed by subsequent
4915 * code emitted by the caller. */
4917 static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4919 vassert(!env->mode64);
4920 iselInt64Expr_wrk(rHi, rLo, env, e);
4921 vassert(hregClass(*rHi) == HRcInt32);
4922 vassert(hregIsVirtual(*rHi));
4923 vassert(hregClass(*rLo) == HRcInt32);
4924 vassert(hregIsVirtual(*rLo));
4927 /* DO NOT CALL THIS DIRECTLY ! */
4928 static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
4930 vassert(e);
4931 vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
4933 /* read 64-bit IRTemp */
4934 if (e->tag == Iex_RdTmp) {
4935 lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
4936 return;
4938 /* 64-bit load */
4939 if (e->tag == Iex_Load) {
4940 HReg tLo = newVRegI(env);
4941 HReg tHi = newVRegI(env);
4942 HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
4943 addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
4944 addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
4945 *rHi = tHi;
4946 *rLo = tLo;
4947 return;
4950 /* 64-bit literal */
4951 if (e->tag == Iex_Const) {
4952 ULong w64 = e->Iex.Const.con->Ico.U64;
4953 UInt wHi = toUInt(w64 >> 32);
4954 UInt wLo = toUInt(w64);
4955 HReg tLo = newVRegI(env);
4956 HReg tHi = newVRegI(env);
4957 vassert(e->Iex.Const.con->tag == Ico_U64);
4959 if (wLo == wHi) {
4960 /* Save a precious Int register in this special case. */
4961 addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
4962 *rHi = tLo;
4963 *rLo = tLo;
4964 } else {
4965 addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
4966 addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
4967 *rHi = tHi;
4968 *rLo = tLo;
4971 return;
4974 /* 64-bit GET */
4975 if (e->tag == Iex_Get) {
4976 HReg tLo = newVRegI(env);
4977 HReg tHi = newVRegI(env);
4979 MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
4980 GuestStatePointer(mode64));
4981 addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
4982 addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
4983 *rHi = tHi;
4984 *rLo = tLo;
4985 return;
4988 /* 64-bit ITE */
4989 if (e->tag == Iex_ITE) {
4990 vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
4991 HReg expr0Lo, expr0Hi;
4992 HReg expr1Lo, expr1Hi;
4993 HReg desLo = newVRegI(env);
4994 HReg desHi = newVRegI(env);
4995 HReg cond = iselWordExpr_R(env, e->Iex.ITE.cond);
4997 /* expr0Hi:expr0Lo = iffalse */
4998 /* expr1Hi:expr1Lo = iftrue */
4999 iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.ITE.iffalse);
5000 iselInt64Expr(&expr1Hi, &expr1Lo, env, e->Iex.ITE.iftrue);
5002 /* move desLo, expr0Lo
5003 * move desHi, expr0Hi
5004 * movn desLo, expr1Lo, cond
5005 * movn desHi, expr1Hi, cond */
5006 #if (__mips_isa_rev >= 6)
5008 HReg r_temp = newVRegI(env);
5009 addInstr(env, MIPSInstr_MoveCond(MSeleqz, desLo, expr0Lo, cond));
5010 addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, expr1Lo, cond));
5011 addInstr(env, MIPSInstr_Alu(Malu_OR, desLo, desLo, MIPSRH_Reg(r_temp)));
5013 addInstr(env, MIPSInstr_MoveCond(MSeleqz, desHi, expr0Hi, cond));
5014 addInstr(env, MIPSInstr_MoveCond(MSelnez, r_temp, expr1Hi, cond));
5015 addInstr(env, MIPSInstr_Alu(Malu_OR, desHi, desHi, MIPSRH_Reg(r_temp)));
5017 #else
5018 addInstr(env, mk_iMOVds_RR(desLo, expr0Lo));
5019 addInstr(env, mk_iMOVds_RR(desHi, expr0Hi));
5020 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desLo, expr1Lo, cond));
5021 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desHi, expr1Hi, cond));
5022 #endif
5024 *rHi = desHi;
5025 *rLo = desLo;
5026 return;
5029 if (e->tag == Iex_CCall) {
5030 HReg r_dstH = newVRegI(env);
5031 HReg r_dstL = newVRegI(env);
5032 vassert(e->Iex.CCall.retty == Ity_I64);
5034 /* Marshal args, do the call, clear stack. */
5035 UInt addToSp = 0;
5036 RetLoc rloc = mk_RetLoc_INVALID();
5037 doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
5038 e->Iex.CCall.retty, e->Iex.CCall.args );
5040 vassert(is_sane_RetLoc(rloc));
5041 vassert(rloc.pri == RLPri_2Int);
5042 vassert(addToSp == 0);
5043 addInstr(env, mk_iMOVds_RR(r_dstL, hregMIPS_GPR2(False)));
5044 addInstr(env, mk_iMOVds_RR(r_dstH, hregMIPS_GPR3(False)));
5045 *rHi = r_dstH;
5046 *rLo = r_dstL;
5047 return;
5050 /* --------- BINARY ops --------- */
5051 if (e->tag == Iex_Binop) {
5052 IROp op_binop = e->Iex.Binop.op;
5053 switch (op_binop) {
5054 /* 32 x 32 -> 64 multiply */
5055 /* Add64 */
5056 case Iop_Add64: {
5057 HReg xLo, xHi, yLo, yHi, carryBit;
5059 HReg tHi = newVRegI(env);
5060 HReg tHi1 = newVRegI(env);
5061 HReg tLo = newVRegI(env);
5063 carryBit = newVRegI(env);
5065 Bool size32 = True;
5066 MIPSCondCode cc = MIPScc_LO;
5068 iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5069 iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5070 addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
5072 /* Check carry. */
5073 addInstr(env, MIPSInstr_Cmp(False, size32, carryBit, tLo, xLo, cc));
5075 addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi1, xHi, MIPSRH_Reg(yHi)));
5076 addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, tHi1,
5077 MIPSRH_Reg(carryBit)));
5079 *rHi = tHi;
5080 *rLo = tLo;
5081 return;
5083 case Iop_Sub64: {
5084 HReg xLo, xHi, yLo, yHi, borrow;
5085 Bool size32 = True;
5086 MIPSCondCode cc = MIPScc_LO;
5088 HReg tHi = newVRegI(env);
5089 HReg tLo = newVRegI(env);
5091 borrow = newVRegI(env);
5093 iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5094 iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5096 addInstr(env, MIPSInstr_Alu(Malu_SUB, tLo, xLo, MIPSRH_Reg(yLo)));
5098 /* Check if borrow is nedded. */
5099 addInstr(env, MIPSInstr_Cmp(False, size32, borrow, xLo, yLo, cc));
5101 addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi,
5102 MIPSRH_Reg(borrow)));
5103 addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, xHi, MIPSRH_Reg(yHi)));
5105 *rHi = tHi;
5106 *rLo = tLo;
5107 return;
5109 case Iop_MullU32:
5110 case Iop_MullS32: {
5111 HReg tLo = newVRegI(env);
5112 HReg tHi = newVRegI(env);
5113 Bool syned = toBool(op_binop == Iop_MullS32);
5114 HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
5115 HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
5116 #if (__mips_isa_rev >= 6)
5117 addInstr(env, MIPSInstr_Mulr6(syned, True, True,
5118 tLo, r_srcL, r_srcR));
5119 addInstr(env, MIPSInstr_Mulr6(syned, True, False,
5120 tHi, r_srcL, r_srcR));
5121 #else
5122 addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
5123 addInstr(env, MIPSInstr_Mfhi(tHi));
5124 addInstr(env, MIPSInstr_Mflo(tLo));
5125 #endif
5126 *rHi = tHi;
5127 *rLo = tLo;
5129 return;
5132 case Iop_DivModU32to32:
5133 case Iop_DivModS32to32: {
5134 HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
5135 HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
5136 HReg tLo = newVRegI(env);
5137 HReg tHi = newVRegI(env);
5138 Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS32to32);
5140 #if (__mips_isa_rev >= 6)
5141 addInstr(env, MIPSInstr_Divr6(syned /*Unsigned or Signed */ ,
5142 True /*32bit or 64bit div */ ,
5143 False /*mod*/,
5144 tLo, r_srcL, r_srcR));
5145 addInstr(env, MIPSInstr_Divr6(syned /*Unsigned or Signed */ ,
5146 True /*32bit or 64bit div */ ,
5147 True /*mod*/,
5148 tHi, r_srcL, r_srcR));
5149 #else
5150 addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
5151 addInstr(env, MIPSInstr_Mfhi(tHi));
5152 addInstr(env, MIPSInstr_Mflo(tLo));
5153 #endif
5154 *rHi = tHi;
5155 *rLo = tLo;
5156 return;
5159 /* 32HLto64(e1,e2) */
5160 case Iop_32HLto64:
5161 *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
5162 *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
5164 return;
5165 /* Or64/And64/Xor64 */
5166 case Iop_Or64:
5167 case Iop_And64:
5168 case Iop_Xor64: {
5169 HReg xLo, xHi, yLo, yHi;
5170 HReg tLo = newVRegI(env);
5171 HReg tHi = newVRegI(env);
5172 MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
5173 (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
5174 iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
5175 iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
5176 addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
5177 addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
5178 *rHi = tHi;
5179 *rLo = tLo;
5180 return;
5183 case Iop_Shr64: {
5184 /* 64-bit logical shift right based on what gcc generates:
5185 <shift>:
5186 nor v0, zero, a2
5187 sll a3, a1, 0x1
5188 sllv a3, a3, v0
5189 srlv v0, a0, a2
5190 srlv v1, a1, a2
5191 andi a0, a2, 0x20
5192 or v0, a3, v0
5193 movn v0, v1, a0
5194 jr ra
5195 movn v1, zero, a0
5197 HReg r_srcLo, r_srcHi;
5198 HReg r_srcLotmp = newVRegI(env);
5199 HReg shift = newVRegI(env);
5200 HReg a3 = newVRegI(env);
5201 HReg r_dstLo = newVRegI(env);
5202 HReg r_dstHi = newVRegI(env);
5203 HReg zero = hregMIPS_GPR0(env->mode64);
5204 MIPSRH *sa = NULL;
5206 iselInt64Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
5207 sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5209 if (sa->tag == Mrh_Imm) {
5210 addInstr(env, MIPSInstr_LI(shift, sa->Mrh.Imm.imm16));
5212 else {
5213 addInstr(env, MIPSInstr_Alu(Malu_AND, shift, sa->Mrh.Reg.reg,
5214 MIPSRH_Imm(False, 0x3f)));
5216 /* nor r_dstLo, zero, shift */
5217 addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(shift)));
5218 /* sll a3, r_srcHi, 0x1 */
5219 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5220 a3, r_srcHi, MIPSRH_Imm(False, 0x1)));
5221 /* sllv a3, a3, r_dstLo */
5222 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5223 a3, a3, MIPSRH_Reg(r_dstLo)));
5224 /* srlv r_dstLo, r_srcLo, shift */
5225 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5226 r_dstLo, r_srcLo, MIPSRH_Reg(shift)));
5227 /* srlv r_dstHi, r_srcHi, shift */
5228 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5229 r_dstHi, r_srcHi, MIPSRH_Reg(shift)));
5230 /* andi r_srcLo, shift, 0x20 */
5231 addInstr(env, MIPSInstr_Alu(Malu_AND, r_srcLotmp, shift,
5232 MIPSRH_Imm(False, 0x20)));
5233 /* or r_dstLo, a3, r_dstLo */
5234 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, a3, MIPSRH_Reg(r_dstLo)));
5235 #if (__mips_isa_rev >= 6)
5236 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, r_srcLotmp));
5237 addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_dstHi, r_srcLotmp));
5238 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, r_dstLo, MIPSRH_Reg(a3)));
5240 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, r_srcLotmp));
5241 #else
5242 /* movn r_dstLo, r_dstHi, r_srcLo */
5243 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, r_dstHi, r_srcLotmp));
5244 /* movn r_dstHi, zero, r_srcLo */
5245 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, zero, r_srcLotmp));
5246 #endif
5247 *rHi = r_dstHi;
5248 *rLo = r_dstLo;
5249 return;
5252 case Iop_Shl64: {
5253 /* 64-bit shift left based on what gcc generates:
5254 <shift>:
5255 nor v0,zero,a2
5256 srl a3,a0,0x1
5257 srlv a3,a3,v0
5258 sllv v1,a1,a2
5259 andi v0,a2,0x20
5260 or v1,a3,v1
5261 sllv a2,a0,a2
5262 movn v1,a2,v0
5263 movn a2,zero,v0
5264 jr ra
5265 move v0,a2
5267 HReg r_srcLo, r_srcHi;
5268 HReg r_shift = newVRegI(env);
5269 HReg a3 = newVRegI(env);
5270 HReg r_dstLo = newVRegI(env);
5271 HReg r_dstHi = newVRegI(env);
5272 HReg zero = hregMIPS_GPR0(env->mode64);
5273 MIPSRH *sa = NULL;
5275 iselInt64Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
5276 sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5278 if (sa->tag == Mrh_Imm) {
5279 addInstr(env, MIPSInstr_LI(r_shift, sa->Mrh.Imm.imm16));
5281 else {
5282 addInstr(env, MIPSInstr_Alu(Malu_AND, r_shift, sa->Mrh.Reg.reg,
5283 MIPSRH_Imm(False, 0x3f)));
5285 /* nor r_dstLo, zero, r_shift */
5286 addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(r_shift)));
5287 /* srl a3, r_srcLo, 0x1 */
5288 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5289 a3, r_srcLo, MIPSRH_Imm(False, 0x1)));
5290 /* srlv a3, a3, r_dstLo */
5291 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5292 a3, a3, MIPSRH_Reg(r_dstLo)));
5293 /* sllv r_dstHi, r_srcHi, r_shift */
5294 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5295 r_dstHi, r_srcHi, MIPSRH_Reg(r_shift)));
5296 /* or r_dstHi, a3, r_dstHi */
5297 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, a3, MIPSRH_Reg(r_dstHi)));
5298 /* andi a3, r_shift, 0x20 */
5299 addInstr(env, MIPSInstr_Alu(Malu_AND, a3, r_shift,
5300 MIPSRH_Imm(False, 0x20)));
5301 /* sllv r_dstLo, r_srcLo, r_shift */
5302 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5303 r_dstLo, r_srcLo, MIPSRH_Reg(r_shift)));
5304 #if (__mips_isa_rev >= 6)
5305 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, a3));
5306 addInstr(env, MIPSInstr_MoveCond(MSelnez, r_shift, r_dstLo, a3));
5307 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, r_dstHi, MIPSRH_Reg(r_shift)));
5309 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, a3));
5310 #else
5311 /* movn r_dstHi, r_dstLo, a3 */
5312 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, r_dstLo, a3));
5313 /* movn r_dstLo, zero, a3 */
5314 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, zero, a3));
5315 #endif
5316 *rHi = r_dstHi;
5317 *rLo = r_dstLo;
5318 return;
5321 case Iop_Sar64: {
5322 /* 64-bit arithmetic shift right based on what gcc generates:
5323 <shift>:
5324 nor v0, zero, a2
5325 sll a3, a1, 0x1
5326 sllv a3, a3, v0
5327 srlv v0, a0, a2
5328 srav v1, a1, a2
5329 andi a0, a2, 0x20
5330 sra a1, a1, 0x1f
5331 or v0, a3, v0
5332 movn v0, v1, a0
5333 jr ra
5334 movn v1, a1, a0
5336 HReg r_srcHi, r_srcLo;
5337 HReg r_srcHitmp = newVRegI(env);
5338 HReg r_srcLotmp = newVRegI(env);
5339 HReg r_shift = newVRegI(env);
5340 HReg a3 = newVRegI(env);
5341 HReg r_dstLo = newVRegI(env);
5342 HReg r_dstHi = newVRegI(env);
5343 HReg zero = hregMIPS_GPR0(env->mode64);
5344 MIPSRH *sa = NULL;
5346 iselInt64Expr(&r_srcLo, &r_srcHi, env, e->Iex.Binop.arg1);
5347 sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
5349 if (sa->tag == Mrh_Imm) {
5350 addInstr(env, MIPSInstr_LI(r_shift, sa->Mrh.Imm.imm16));
5352 else {
5353 addInstr(env, MIPSInstr_Alu(Malu_AND, r_shift, sa->Mrh.Reg.reg,
5354 MIPSRH_Imm(False, 0x3f)));
5356 /* nor r_dstLo, zero, r_shift */
5357 addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dstLo, zero, MIPSRH_Reg(r_shift)));
5358 /* sll a3, r_srcLo, 0x1 */
5359 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5360 a3, r_srcLo, MIPSRH_Imm(False, 0x1)));
5361 /* sllv a3, a3, r_dstLo */
5362 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
5363 a3, a3, MIPSRH_Reg(r_dstLo)));
5364 /* srlv r_dstLo, r_srcHi, r_shift */
5365 addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
5366 r_dstLo, r_srcHi, MIPSRH_Reg(r_shift)));
5367 /* srav r_dstHi, r_srcLo, r_shift */
5368 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
5369 r_dstHi, r_srcLo, MIPSRH_Reg(r_shift)));
5370 /* andi r_srcHi, r_shift, 0x20 */
5371 addInstr(env, MIPSInstr_Alu(Malu_AND, r_srcHitmp, r_shift,
5372 MIPSRH_Imm(False, 0x20)));
5373 /* sra r_srcLo, r_srcLo, 0x1f */
5374 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
5375 r_srcLotmp, r_srcLo, MIPSRH_Imm(False, 0x1f)));
5376 /* or r_dstLo, a3, r_dstLo */
5377 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, a3, MIPSRH_Reg(r_dstLo)));
5378 #if (__mips_isa_rev >= 6)
5379 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstLo, r_dstLo, r_srcHitmp));
5380 addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_dstHi, r_srcHitmp));
5381 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstLo, r_dstLo, MIPSRH_Reg(a3)));
5383 addInstr(env, MIPSInstr_MoveCond(MSeleqz, r_dstHi, r_dstHi, r_srcHitmp));
5384 addInstr(env, MIPSInstr_MoveCond(MSelnez, a3, r_srcLotmp, r_srcHitmp));
5385 addInstr(env, MIPSInstr_Alu(Malu_OR, r_dstHi, r_dstHi, MIPSRH_Reg(a3)));
5386 #else
5387 /* movn r_dstLo, r_dstHi, r_srcHi */
5388 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstLo, r_dstHi, r_srcHitmp));
5389 /* movn r_dstHi, r_srcLo, r_srcHi */
5390 addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dstHi, r_srcLotmp, r_srcHitmp));
5391 #endif
5392 *rHi = r_dstHi;
5393 *rLo = r_dstLo;
5394 return;
5397 case Iop_F32toI64S: {
5398 HReg tmpD = newVRegD(env);
5399 HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
5400 HReg tLo = newVRegI(env);
5401 HReg tHi = newVRegI(env);
5402 MIPSAMode *am_addr;
5404 /* CVTLS tmpD, valF */
5405 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
5406 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
5407 set_MIPS_rounding_default(env);
5409 sub_from_sp(env, 16); /* Move SP down 16 bytes */
5410 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5412 /* store as F64 */
5413 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
5414 am_addr));
5415 /* load as 2xI32 */
5416 #if defined (_MIPSEL)
5417 addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5418 addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5419 mode64));
5420 #elif defined (_MIPSEB)
5421 addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5422 addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5423 mode64));
5424 #endif
5426 /* Reset SP */
5427 add_to_sp(env, 16);
5429 *rHi = tHi;
5430 *rLo = tLo;
5432 return;
5434 case Iop_F64toI64U: {
5435 HReg r_src;
5436 HReg tmp = newVRegV(env);
5437 vassert(has_msa);
5438 r_src = iselDblExpr( env, e->Iex.Binop.arg2);
5439 set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
5440 addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_U, MSA_F_DW, tmp, r_src));
5441 HReg r_dsth = newVRegI(env);
5442 HReg r_dstl = newVRegI(env);
5443 addInstr(env,
5444 MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_dstl, MSA_DFN_W | 0));
5445 addInstr(env,
5446 MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_dsth, MSA_DFN_W | 1));
5447 *rHi = r_dsth;
5448 *rLo = r_dstl;
5449 set_MIPS_rounding_default_MSA(env);
5450 return;
5453 case Iop_GetElem64x2: {
5454 vassert(has_msa);
5455 HReg v_src = iselV128Expr(env, e->Iex.Binop.arg1);
5456 HReg r_dstHI = newVRegI(env);
5457 HReg r_dstLO = newVRegI(env);
5458 MIPSRH *tmp = iselWordExpr_RH(env, False, e->Iex.Binop.arg2);
5460 switch (tmp->tag) {
5461 case Mrh_Imm:
5462 addInstr(env,
5463 MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dstHI,
5464 MSA_DFN_W |
5465 (((tmp->Mrh.Imm.imm16 & 0x01) << 1)
5466 + 1)));
5467 addInstr(env,
5468 MIPSInstr_MsaElm(MSA_COPY_S, v_src, r_dstLO,
5469 MSA_DFN_W |
5470 ((tmp->Mrh.Imm.imm16 & 0x01) << 1)));
5471 break;
5473 case Mrh_Reg: {
5474 HReg v_tmp = newVRegV(env);
5475 addInstr(env,
5476 MIPSInstr_Msa3R(MSA_SPLAT, MSA_D, v_tmp, v_src,
5477 tmp->Mrh.Reg.reg));
5478 addInstr(env,
5479 MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dstHI,
5480 MSA_DFN_W | 1));
5481 addInstr(env,
5482 MIPSInstr_MsaElm(MSA_COPY_S, v_tmp, r_dstLO,
5483 MSA_DFN_W));
5484 break;
5488 *rHi = r_dstHI;
5489 *rLo = r_dstLO;
5490 return;
5493 case Iop_Mul64: {
5494 HReg a_L, a_H, b_L, b_H;
5495 HReg dst_L = newVRegI(env);
5496 HReg dst_H = newVRegI(env);
5498 iselInt64Expr(&a_H, &a_L, env, e->Iex.Binop.arg1);
5499 iselInt64Expr(&b_H, &b_L, env, e->Iex.Binop.arg2);
5500 #if (__mips_isa_rev >= 6)
5501 addInstr(env, MIPSInstr_Mulr6(True, True, True,
5502 dst_H, a_H, b_L));
5503 addInstr(env, MIPSInstr_Mulr6(True, True, True,
5504 dst_L, b_H, a_L));
5505 addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5506 MIPSRH_Reg(dst_L)));
5507 addInstr(env, MIPSInstr_Mulr6(False, True, False,
5508 dst_L, a_L, b_L));
5510 addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5511 MIPSRH_Reg(dst_L)));
5512 addInstr(env, MIPSInstr_Mulr6(False, True, True,
5513 dst_L, a_L, b_L));
5514 #else
5515 addInstr(env, MIPSInstr_Mul(dst_H, a_H, b_L));
5516 addInstr(env, MIPSInstr_Mult(True, b_H, a_L));
5517 addInstr(env, MIPSInstr_Mflo(dst_L));
5518 addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5519 MIPSRH_Reg(dst_L)));
5520 addInstr(env, MIPSInstr_Mult(False, a_L, b_L));
5521 addInstr(env, MIPSInstr_Mfhi(dst_L));
5523 addInstr(env, MIPSInstr_Alu(Malu_ADD, dst_H, dst_H,
5524 MIPSRH_Reg(dst_L)));
5525 addInstr(env, MIPSInstr_Mflo(dst_L));
5526 #endif
5527 *rHi = dst_H;
5528 *rLo = dst_L;
5529 return;
5532 case Iop_DivS64: {
5533 HReg src1_L, src1_H, src2_L, src2_H;
5534 HReg dst_L = newVRegI(env);
5535 HReg dst_H = newVRegI(env);
5536 HReg tmp1 = newVRegV(env);
5537 HReg tmp2 = newVRegV(env);
5538 vassert(has_msa);
5539 iselInt64Expr(&src1_H, &src1_L, env, e->Iex.Binop.arg1);
5540 iselInt64Expr(&src2_H, &src2_L, env, e->Iex.Binop.arg2);
5541 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src1_L, tmp1));
5542 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src1_H, tmp1, MSA_DFN_W | 1));
5543 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src2_L, tmp2));
5544 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src2_H, tmp2, MSA_DFN_W | 1));
5545 addInstr(env, MIPSInstr_Msa3R(MSA_DIVS, MSA_D, tmp1, tmp1, tmp2));
5546 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_H, MSA_DFN_W | 1));
5547 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_L, MSA_DFN_W | 0));
5548 *rHi = dst_H;
5549 *rLo = dst_L;
5550 return;
5553 case Iop_DivU64: {
5554 HReg src1_L, src1_H, src2_L, src2_H;
5555 HReg dst_L = newVRegI(env);
5556 HReg dst_H = newVRegI(env);
5557 HReg tmp1 = newVRegV(env);
5558 HReg tmp2 = newVRegV(env);
5559 vassert(has_msa);
5560 iselInt64Expr(&src1_H, &src1_L, env, e->Iex.Binop.arg1);
5561 iselInt64Expr(&src2_H, &src2_L, env, e->Iex.Binop.arg2);
5562 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src1_L, tmp1));
5563 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src1_H, tmp1, MSA_DFN_W | 1));
5564 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, src2_L, tmp2));
5565 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, src2_H, tmp2, MSA_DFN_W | 1));
5566 addInstr(env, MIPSInstr_Msa3R(MSA_DIVU, MSA_D, tmp1, tmp1, tmp2));
5567 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_H, MSA_DFN_W | 1));
5568 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp1, dst_L, MSA_DFN_W | 0));
5569 *rHi = dst_H;
5570 *rLo = dst_L;
5571 return;
5574 case Iop_F64toI64S: {
5575 HReg tmpD = newVRegD(env);
5576 HReg valF;
5577 HReg tLo = newVRegI(env);
5578 HReg tHi = newVRegI(env);
5579 MIPSAMode *am_addr;
5581 if(mode64){
5582 valF = iselFltExpr(env, e->Iex.Binop.arg2);
5583 } else {
5584 valF = iselDblExpr(env, e->Iex.Binop.arg2);
5587 /* CVTLS tmpD, valF */
5588 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
5589 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, tmpD, valF));
5590 set_MIPS_rounding_default(env);
5592 sub_from_sp(env, 16); /* Move SP down 16 bytes */
5593 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5595 /* store as F64 */
5596 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
5597 am_addr));
5598 /* load as 2xI32 */
5599 #if defined (_MIPSEL)
5600 addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5601 addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5602 mode64));
5603 #elif defined (_MIPSEB)
5604 addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5605 addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5606 mode64));
5607 #endif
5609 /* Reset SP */
5610 add_to_sp(env, 16);
5612 *rHi = tHi;
5613 *rLo = tLo;
5615 return;
5618 default:
5619 break;
5623 /* --------- UNARY ops --------- */
5624 if (e->tag == Iex_Unop) {
5625 switch (e->Iex.Unop.op) {
5626 case Iop_1Sto64: {
5627 HReg tLo = newVRegI(env);
5628 HReg tHi = newVRegI(env);
5629 HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5630 HReg tmp = newVRegI(env);
5632 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
5633 MIPSRH_Imm(False, 31)));
5634 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
5635 MIPSRH_Imm(False, 31)));
5637 addInstr(env, mk_iMOVds_RR(tHi, tmp));
5638 addInstr(env, mk_iMOVds_RR(tLo, tmp));
5640 *rHi = tHi;
5641 *rLo = tLo;
5642 return;
5645 case Iop_8Sto64:
5646 case Iop_16Sto64: {
5647 HReg tLo = newVRegI(env);
5648 HReg tHi = newVRegI(env);
5649 HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5650 UInt no_bits = (e->Iex.Unop.op == Iop_8Sto64) ? 24 : 16;
5651 addInstr(env, mk_iMOVds_RR(tLo, src));
5652 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tLo, tLo,
5653 MIPSRH_Imm(False, no_bits)));
5654 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tLo,
5655 MIPSRH_Imm(False, 31)));
5656 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tLo, tLo,
5657 MIPSRH_Imm(False, no_bits)));
5658 addInstr(env, mk_iMOVds_RR(tHi, tLo));
5659 *rHi = tHi;
5660 *rLo = tLo;
5661 return;
5664 /* 32Sto64(e) */
5665 case Iop_32Sto64: {
5666 HReg tLo = newVRegI(env);
5667 HReg tHi = newVRegI(env);
5668 HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5669 addInstr(env, mk_iMOVds_RR(tHi, src));
5670 addInstr(env, mk_iMOVds_RR(tLo, src));
5671 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
5672 MIPSRH_Imm(False, 31)));
5673 *rHi = tHi;
5674 *rLo = tLo;
5675 return;
5678 case Iop_8Uto64:
5679 case Iop_16Uto64: {
5680 HReg tLo = newVRegI(env);
5681 HReg tHi = newVRegI(env);
5682 HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5683 UInt mask = (e->Iex.Unop.op == Iop_8Sto64) ? 0xFF : 0xFFFF;
5684 addInstr(env, MIPSInstr_Alu(Malu_AND, tLo, src,
5685 MIPSRH_Imm(False, mask)));
5686 addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
5687 MIPSRH_Reg(hregMIPS_GPR0(mode64))));
5688 *rHi = tHi;
5689 *rLo = tLo;
5690 return;
5693 /* 32Uto64(e) */
5694 case Iop_32Uto64: {
5695 HReg tLo = newVRegI(env);
5696 HReg tHi = newVRegI(env);
5697 HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
5698 addInstr(env, mk_iMOVds_RR(tLo, src));
5699 addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
5700 MIPSRH_Reg(hregMIPS_GPR0(mode64))));
5701 *rHi = tHi;
5702 *rLo = tLo;
5703 return;
5706 case Iop_Left64: {
5707 HReg yHi, yLo;
5708 HReg tHi = newVRegI(env);
5709 HReg tLo = newVRegI(env);
5710 HReg tmp = newVRegI(env);
5711 HReg tmp1 = newVRegI(env);
5712 HReg tmp2 = newVRegI(env);
5713 HReg zero = newVRegI(env);
5714 MIPSCondCode cc = MIPScc_LO;
5716 /* yHi:yLo = arg */
5717 iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
5718 /* zero = 0 */
5719 addInstr(env, MIPSInstr_LI(zero, 0x00000000));
5721 /* tmp2:tmp1 = 0 - (yHi:yLo)*/
5722 addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, zero, MIPSRH_Reg(yLo)));
5723 addInstr(env, MIPSInstr_Cmp(False, True, tmp1, zero, tmp2, cc));
5724 addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, zero, MIPSRH_Reg(yHi)));
5725 addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp1, tmp, MIPSRH_Reg(tmp1)));
5727 /* So now we have tmp2:tmp1 = -arg. To finish off, or 'arg'
5728 back in, so as to give the final result
5729 tHi:tLo = arg | -arg. */
5730 addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, yHi, MIPSRH_Reg(tmp1)));
5731 addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, yLo, MIPSRH_Reg(tmp2)));
5732 *rHi = tHi;
5733 *rLo = tLo;
5734 return;
5737 case Iop_CmpwNEZ64: {
5738 HReg srcLo, srcHi;
5739 HReg tmp1 = newVRegI(env);
5740 HReg tmp2 = newVRegI(env);
5741 /* srcHi:srcLo = arg */
5742 iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
5743 /* tmp1 = srcHi | srcLo */
5744 addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
5745 MIPSRH_Reg(srcHi)));
5746 /* tmp2 = (tmp1 | -tmp1) >>s 31 */
5748 addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
5749 MIPSRH_Reg(tmp1)));
5751 addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
5752 addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
5753 MIPSRH_Imm(False, 31)));
5754 *rHi = tmp2;
5755 *rLo = tmp2;
5756 return;
5759 case Iop_ReinterpF64asI64: {
5760 HReg tLo = newVRegI(env);
5761 HReg tHi = newVRegI(env);
5762 MIPSAMode *am_addr;
5763 HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
5765 sub_from_sp(env, 16); /* Move SP down 16 bytes */
5766 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
5768 /* store as F64 */
5769 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
5770 am_addr));
5771 /* load as 2xI32 */
5772 #if defined (_MIPSEL)
5773 addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
5774 addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
5775 mode64));
5776 #elif defined (_MIPSEB)
5777 addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
5778 addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
5779 mode64));
5780 #endif
5782 /* Reset SP */
5783 add_to_sp(env, 16);
5785 *rHi = tHi;
5786 *rLo = tLo;
5787 return;
5790 case Iop_Not64: {
5791 HReg tLo = newVRegI(env);
5792 HReg tHi = newVRegI(env);
5793 iselInt64Expr(&tHi, &tLo, env, e->Iex.Unop.arg);
5794 addInstr(env, MIPSInstr_Alu(Malu_NOR, tLo, tLo, MIPSRH_Reg(tLo)));
5795 addInstr(env, MIPSInstr_Alu(Malu_NOR, tHi, tHi, MIPSRH_Reg(tHi)));
5797 *rHi = tHi;
5798 *rLo = tLo;
5799 return;
5802 case Iop_V128HIto64: {
5803 vassert(has_msa);
5804 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
5805 HReg tLo = newVRegI(env);
5806 HReg tHi = newVRegI(env);
5807 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 2));
5808 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 3));
5809 *rLo = tLo;
5810 *rHi = tHi;
5811 return;
5814 case Iop_V128to64: {
5815 vassert(has_msa);
5816 HReg v_src = iselV128Expr(env, e->Iex.Unop.arg);
5817 HReg tLo = newVRegI(env);
5818 HReg tHi = newVRegI(env);
5819 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 0));
5820 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 1));
5821 *rLo = tLo;
5822 *rHi = tHi;
5823 return;
5826 case Iop_F32toF16x4_DEP: {
5827 vassert(has_msa);
5828 HReg v_arg = iselV128Expr(env, e->Iex.Unop.arg);
5829 HReg v_src = newVRegV(env);
5830 set_guest_MIPS_rounding_mode_MSA(env);
5831 addInstr(env, MIPSInstr_Msa3RF(MSA_FEXDO, MSA_F_WH, v_src, v_arg, v_arg));
5832 set_MIPS_rounding_default_MSA(env);
5833 HReg tLo = newVRegI(env);
5834 HReg tHi = newVRegI(env);
5835 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tLo, MSA_DFN_W | 0));
5836 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, v_src, tHi, MSA_DFN_W | 1));
5837 *rLo = tLo;
5838 *rHi = tHi;
5839 return;
5842 default:
5843 vex_printf("UNARY: No such op: ");
5844 ppIROp(e->Iex.Unop.op);
5845 vex_printf("\n");
5846 break;
5850 vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
5851 ppIRExpr(e);
5852 vpanic("iselInt64Expr(mips)");
5855 /*---------------------------------------------------------*/
5856 /*--- ISEL: Floating point expressions (32 bit) ---*/
5857 /*---------------------------------------------------------*/
5859 /* Nothing interesting here; really just wrappers for
5860 64-bit stuff. */
5861 static HReg iselFltExpr(ISelEnv * env, IRExpr * e)
5863 HReg r;
5864 IRType ty = typeOfIRExpr(env->type_env, e);
5865 if (ty == Ity_F32 || (ty == Ity_F64 && fp_mode64)) {
5866 r = iselFltExpr_wrk(env, e);
5867 } else {
5868 r = iselDblExpr_wrk(env, e);
5869 vassert(hregClass(r) == HRcFlt64);
5871 return r;
5874 /* DO NOT CALL THIS DIRECTLY */
5875 static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
5877 IRType ty = typeOfIRExpr(env->type_env, e);
5878 vassert(ty == Ity_F32 || (ty == Ity_F64 && fp_mode64));
5880 if (e->tag == Iex_RdTmp) {
5881 return lookupIRTemp(env, e->Iex.RdTmp.tmp);
5884 if (e->tag == Iex_Load) {
5885 vassert(e->Iex.Load.ty == Ity_F32
5886 || (e->Iex.Load.ty == Ity_F64 && fp_mode64));
5887 HReg r_dst;
5888 MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
5889 if (e->Iex.Load.ty == Ity_F64) {
5890 r_dst = newVRegD(env);
5891 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
5892 } else {
5893 r_dst = newVRegF(env);
5894 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
5896 return r_dst;
5899 if (e->tag == Iex_Get) {
5900 MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
5901 GuestStatePointer(mode64));
5902 HReg r_dst;
5903 if (e->Iex.Load.ty == Ity_F64) {
5904 r_dst = newVRegD(env);
5905 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
5906 } else {
5907 r_dst = newVRegF(env);
5908 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
5910 return r_dst;
5913 if (e->tag == Iex_Unop) {
5914 switch (e->Iex.Unop.op) {
5915 case Iop_ReinterpI32asF32: {
5916 HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5917 HReg r_dst = newVRegF(env);
5919 /* Move Word to Floating Point
5920 mtc1 r_dst, valS */
5921 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, fr_src));
5923 return r_dst;
5925 case Iop_F32toF64: {
5926 vassert(fp_mode64);
5927 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5928 HReg dst = newVRegD(env);
5930 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
5931 return dst;
5933 case Iop_ReinterpI64asF64: {
5934 HReg r_dst;
5935 if (mode64) {
5936 HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5937 r_dst = newVRegF(env);
5938 /* Move Doubleword to Floating Point
5939 dmtc1 r_dst, fr_src */
5940 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
5941 } else {
5942 HReg Hi, Lo;
5943 r_dst = newVRegD(env);
5944 iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
5945 r_dst = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
5947 return r_dst;
5949 case Iop_I32StoF64: {
5950 vassert(fp_mode64);
5951 HReg dst = newVRegF(env);
5952 HReg tmp = newVRegF(env);
5953 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
5955 /* Move Word to Floating Point
5956 mtc1 tmp, r_src */
5957 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
5959 /* and do convert */
5960 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
5962 return dst;
5964 case Iop_AbsF32:
5965 case Iop_AbsF64: {
5966 Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
5967 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5968 HReg dst = newVRegF(env);
5969 addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
5970 return dst;
5972 case Iop_NegF32:
5973 case Iop_NegF64: {
5974 Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
5975 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5976 HReg dst = newVRegF(env);
5977 addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
5978 return dst;
5980 case Iop_RoundF64toF64_ZERO: {
5981 vassert(mode64);
5982 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5983 HReg dst = newVRegF(env);
5984 addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, dst, src));
5985 return dst;
5987 case Iop_RoundF64toF64_NEAREST: {
5988 vassert(mode64);
5989 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5990 HReg dst = newVRegF(env);
5991 addInstr(env, MIPSInstr_FpConvert(Mfp_ROUNDLD, dst, src));
5992 return dst;
5994 case Iop_RoundF64toF64_NegINF: {
5995 vassert(mode64);
5996 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
5997 HReg dst = newVRegF(env);
5998 addInstr(env, MIPSInstr_FpConvert(Mfp_FLOORLD, dst, src));
5999 return dst;
6001 case Iop_RoundF64toF64_PosINF: {
6002 vassert(mode64);
6003 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
6004 HReg dst = newVRegF(env);
6005 addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, dst, src));
6006 return dst;
6009 default:
6010 break;
6014 if (e->tag == Iex_Triop) {
6015 switch (e->Iex.Triop.details->op) {
6016 case Iop_DivF32:
6017 case Iop_DivF64:
6018 case Iop_MulF32:
6019 case Iop_MulF64:
6020 case Iop_AddF32:
6021 case Iop_AddF64:
6022 case Iop_SubF32:
6023 case Iop_SubF64: {
6024 MIPSFpOp op = 0;
6025 HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
6026 HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
6027 HReg dst = newVRegF(env);
6028 switch (e->Iex.Triop.details->op) {
6029 case Iop_DivF32:
6030 op = Mfp_DIVS;
6031 break;
6032 case Iop_DivF64:
6033 vassert(fp_mode64);
6034 op = Mfp_DIVD;
6035 break;
6036 case Iop_MulF32:
6037 op = Mfp_MULS;
6038 break;
6039 case Iop_MulF64:
6040 vassert(fp_mode64);
6041 op = Mfp_MULD;
6042 break;
6043 case Iop_AddF32:
6044 op = Mfp_ADDS;
6045 break;
6046 case Iop_AddF64:
6047 vassert(fp_mode64);
6048 op = Mfp_ADDD;
6049 break;
6050 case Iop_SubF32:
6051 op = Mfp_SUBS;
6052 break;
6053 case Iop_SubF64:
6054 vassert(fp_mode64);
6055 op = Mfp_SUBD;
6056 break;
6057 default:
6058 vassert(0);
6060 set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
6061 addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
6062 set_MIPS_rounding_default(env);
6063 return dst;
6065 case Iop_ScaleF64: {
6066 HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
6067 HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
6068 HReg v_help = newVRegV(env);
6069 HReg dst = newVRegF(env);
6070 vassert(has_msa);
6071 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
6072 addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_S, MSA_F_DW, v_help, src2));
6073 addInstr(env, MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW, dst, src1, v_help));
6074 set_MIPS_rounding_default_MSA(env);
6076 return dst;
6078 default:
6079 break;
6083 if (e->tag == Iex_Binop) {
6084 switch (e->Iex.Binop.op) {
6085 case Iop_F64toF32: {
6086 HReg valD;
6087 if (mode64)
6088 valD = iselFltExpr(env, e->Iex.Binop.arg2);
6089 else
6090 valD = iselDblExpr(env, e->Iex.Binop.arg2);
6091 HReg valS = newVRegF(env);
6093 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6094 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
6095 set_MIPS_rounding_default(env);
6096 return valS;
6099 case Iop_RoundF32toInt: {
6100 HReg valS = newVRegF(env);
6101 HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
6103 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6104 #if (__mips_isa_rev >= 6)
6105 addInstr(env, MIPSInstr_FpConvert(Mfp_RINTS, valS, valF));
6106 #else
6107 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
6108 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, valS, valS));
6109 #endif
6110 set_MIPS_rounding_default(env);
6111 return valS;
6114 case Iop_RoundF64toInt: {
6115 HReg valS = newVRegF(env);
6116 HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
6118 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6119 #if (__mips_isa_rev >= 6)
6120 addInstr(env, MIPSInstr_FpConvert(Mfp_RINTD, valS, valF));
6121 #else
6122 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, valS, valF));
6123 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, valS, valS));
6125 #endif
6126 set_MIPS_rounding_default(env);
6127 return valS;
6130 case Iop_I32StoF32: {
6131 HReg r_dst = newVRegF(env);
6132 HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6133 HReg tmp = newVRegF(env);
6135 /* Move Word to Floating Point
6136 mtc1 tmp, fr_src */
6137 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, fr_src));
6139 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6140 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
6141 set_MIPS_rounding_default(env);
6143 return r_dst;
6146 case Iop_I64StoF64: {
6147 HReg r_dst = newVRegF(env);
6148 MIPSAMode *am_addr;
6149 HReg tmp, fr_src;
6150 if (mode64) {
6151 tmp = newVRegF(env);
6152 fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6153 /* Move SP down 8 bytes */
6154 sub_from_sp(env, 8);
6155 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6157 /* store as I64 */
6158 addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6160 /* load as Ity_F64 */
6161 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6163 /* Reset SP */
6164 add_to_sp(env, 8);
6165 } else {
6166 HReg Hi, Lo;
6167 tmp = newVRegD(env);
6168 iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6169 tmp = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
6172 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6173 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6174 set_MIPS_rounding_default(env);
6176 return r_dst;
6179 case Iop_I64StoF32: {
6180 HReg r_dst = newVRegF(env);
6181 MIPSAMode *am_addr;
6182 HReg fr_src, tmp;
6183 if (mode64) {
6184 tmp = newVRegF(env);
6185 fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6186 /* Move SP down 8 bytes */
6187 sub_from_sp(env, 8);
6188 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6190 /* store as I64 */
6191 addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6193 /* load as Ity_F64 */
6194 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6196 /* Reset SP */
6197 add_to_sp(env, 8);
6198 } else {
6199 HReg Hi, Lo;
6200 tmp = newVRegD(env);
6201 iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6202 tmp = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
6205 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6206 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSL, r_dst, tmp));
6207 set_MIPS_rounding_default(env);
6209 return r_dst;
6212 case Iop_SqrtF32:
6213 case Iop_SqrtF64: {
6214 Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
6215 HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
6216 HReg dst = newVRegF(env);
6217 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6218 addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
6219 src));
6220 set_MIPS_rounding_default(env);
6221 return dst;
6224 case Iop_I64UtoF64: {
6225 vassert(mode64);
6226 HReg r_dst = newVRegF(env);
6227 HReg tmp = newVRegV(env);
6228 HReg r_src;
6229 vassert(has_msa);
6230 r_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6231 set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
6232 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_D, r_src, tmp));
6233 HReg r_srch = newVRegI(env);
6234 addInstr(env, MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_DW, tmp, tmp));
6235 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srch, MSA_DFN_D | 0));
6236 sub_from_sp(env, 8);
6237 MIPSAMode *am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6239 /* store as I64 */
6240 addInstr(env, MIPSInstr_Store(8, am_addr, r_srch, mode64));
6242 /* load as Ity_F64 */
6243 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
6245 /* Reset SP */
6246 add_to_sp(env, 8);
6247 set_MIPS_rounding_default_MSA(env);
6248 return r_dst;
6251 #if (__mips_isa_rev >= 6)
6252 case Iop_MaxNumF32: {
6253 HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6254 HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6255 HReg dst = newVRegF(env);
6256 addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXS, dst,
6257 src1, src2));
6258 return dst;
6261 case Iop_MaxNumF64: {
6262 HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6263 HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6264 HReg dst = newVRegF(env);
6265 addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXD, dst,
6266 src1, src2));
6267 return dst;
6270 case Iop_MinNumF32: {
6271 HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6272 HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6273 HReg dst = newVRegF(env);
6274 addInstr(env, MIPSInstr_FpMinMax(Mfp_MINS, dst,
6275 src1, src2));
6276 return dst;
6279 case Iop_MinNumF64: {
6280 HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
6281 HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
6282 HReg dst = newVRegF(env);
6283 addInstr(env, MIPSInstr_FpMinMax(Mfp_MIND, dst,
6284 src1, src2));
6285 return dst;
6287 #endif
6288 default:
6289 break;
6293 if (e->tag == Iex_Qop) {
6294 switch (e->Iex.Qop.details->op) {
6295 case Iop_MAddF32:
6296 case Iop_MAddF64:
6297 case Iop_MSubF32:
6298 case Iop_MSubF64: {
6299 Int op = 0;
6300 #if (__mips_isa_rev < 6)
6301 MSADFFlx type = 0;
6302 #endif
6303 switch (e->Iex.Qop.details->op) {
6304 #if (__mips_isa_rev >= 6)
6305 case Iop_MAddF32:
6306 op = Mfp_MADDS;
6307 break;
6308 case Iop_MAddF64:
6309 op = Mfp_MADDD;
6310 break;
6311 case Iop_MSubF32:
6312 op = Mfp_MSUBS;
6313 break;
6314 case Iop_MSubF64:
6315 op = Mfp_MSUBD;
6316 break;
6317 #else
6318 case Iop_MAddF32:
6319 op = has_msa ? MSA_FMADD : Mfp_MADDS;
6320 type = MSA_F_WH;
6321 break;
6322 case Iop_MAddF64:
6323 op = has_msa ? MSA_FMADD : Mfp_MADDD;
6324 type = MSA_F_DW;
6325 break;
6326 case Iop_MSubF32:
6327 op = has_msa ? MSA_FMSUB : Mfp_MSUBS;
6328 type = MSA_F_WH;
6329 break;
6330 case Iop_MSubF64:
6331 op = has_msa ? MSA_FMSUB : Mfp_MSUBD;
6332 type = MSA_F_DW;
6333 break;
6334 #endif
6335 default:
6336 vassert(0);
6339 HReg dst = newVRegF(env);
6340 HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
6341 HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
6342 HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
6343 #if (__mips_isa_rev >= 6)
6344 set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6345 addInstr(env, MIPSInstr_FpTernary(op, dst,
6346 src3, src1, src2));
6347 set_MIPS_rounding_default(env);
6348 #else
6349 if (has_msa) {
6350 addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, src3, dst, 0));
6351 set_MIPS_rounding_mode_MSA(env, e->Iex.Qop.details->arg1);
6352 addInstr(env, MIPSInstr_Msa3RF(op, type, dst, src1, src2));
6353 set_MIPS_rounding_default_MSA(env);
6354 } else {
6355 set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6356 addInstr(env, MIPSInstr_FpTernary(op, dst,
6357 src1, src2, src3));
6358 set_MIPS_rounding_default(env);
6360 #endif
6361 return dst;
6364 default:
6365 break;
6369 if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
6370 /* This is quite subtle. The only way to do the relevant
6371 truncation is to do a single-precision store and then a
6372 double precision load to get it back into a register. The
6373 problem is, if the data is then written to memory a second
6374 time, as in
6376 STbe(...) = TruncF64asF32(...)
6378 then will the second truncation further alter the value? The
6379 answer is no: flds (as generated here) followed by fsts
6380 (generated for the STbe) is the identity function on 32-bit
6381 floats, so we are safe.
6383 Another upshot of this is that if iselStmt can see the
6384 entirety of
6386 STbe(...) = TruncF64asF32(arg)
6388 then it can short circuit having to deal with TruncF64asF32
6389 individually; instead just compute arg into a 64-bit FP
6390 register and do 'fsts' (since that itself does the
6391 truncation).
6393 We generate pretty poor code here (should be ok both for
6394 32-bit and 64-bit mode); but it is expected that for the most
6395 part the latter optimisation will apply and hence this code
6396 will not often be used.
6398 HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
6399 HReg fdst = newVRegF(env);
6400 MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
6402 sub_from_sp(env, 16);
6403 /* store as F32, hence truncating */
6404 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
6405 /* and reload. Good huh?! (sigh) */
6406 addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
6407 add_to_sp(env, 16);
6408 return fdst;
6411 /* --------- ITE --------- */
6412 if (e->tag == Iex_ITE) {
6413 vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
6414 HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
6415 HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
6416 HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
6417 HReg r_dst = newVRegF(env);
6418 #if (__mips_isa_rev >= 6)
6419 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, r_cond));
6420 addInstr(env, MIPSInstr_MoveCond(MFpSeld, r_dst, r0, r1));
6421 #else
6422 addInstr(env, MIPSInstr_FpUnary((ty == Ity_F64) ? Mfp_MOVD : Mfp_MOVS,
6423 r_dst, r0));
6424 addInstr(env, MIPSInstr_MoveCond((ty == Ity_F64) ? MFpMoveCond_movnd :
6425 MFpMoveCond_movns,
6426 r_dst, r1, r_cond));
6427 #endif
6428 return r_dst;
6431 vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
6432 ppIRExpr(e);
6433 vpanic("iselFltExpr_wrk(mips)");
6436 static HReg iselDblExpr(ISelEnv * env, IRExpr * e)
6438 HReg r = iselDblExpr_wrk(env, e);
6439 vassert(hregClass(r) == HRcFlt64);
6440 vassert(hregIsVirtual(r));
6441 return r;
6444 /* DO NOT CALL THIS DIRECTLY */
6445 static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
6447 IRType ty = typeOfIRExpr(env->type_env, e);
6448 vassert(e);
6449 vassert(ty == Ity_F64);
6451 if (e->tag == Iex_RdTmp) {
6452 return lookupIRTemp(env, e->Iex.RdTmp.tmp);
6455 /* --------- LOAD --------- */
6456 if (e->tag == Iex_Load) {
6457 HReg r_dst = newVRegD(env);
6458 MIPSAMode *am_addr;
6459 vassert(e->Iex.Load.ty == Ity_F64);
6460 am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
6461 addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
6462 return r_dst;
6465 /* --------- GET --------- */
6466 if (e->tag == Iex_Get) {
6468 HReg r_dst = newVRegD(env);
6469 MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
6470 GuestStatePointer(mode64));
6471 addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
6472 return r_dst;
6475 if (e->tag == Iex_Unop) {
6476 MIPSFpOp fpop = Mfp_INVALID;
6477 switch (e->Iex.Unop.op) {
6478 case Iop_NegF64:
6479 fpop = Mfp_NEGD;
6480 break;
6481 case Iop_AbsF64:
6482 fpop = Mfp_ABSD;
6483 break;
6484 case Iop_F32toF64: {
6485 vassert(!mode64);
6486 HReg src = iselFltExpr(env, e->Iex.Unop.arg);
6487 HReg dst = newVRegD(env);
6489 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
6490 return dst;
6492 case Iop_ReinterpI64asF64: {
6493 HReg Hi, Lo;
6494 HReg dst = newVRegD(env);
6496 iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
6498 dst = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
6499 return dst;
6501 case Iop_I32StoF64: {
6502 vassert(!mode64);
6503 HReg dst = newVRegD(env);
6504 HReg tmp = newVRegF(env);
6505 HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
6507 /* Move Word to Floating Point
6508 mtc1 tmp, r_src */
6509 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
6511 /* and do convert */
6512 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
6514 return dst;
6516 default:
6517 break;
6520 if (fpop != Mfp_INVALID) {
6521 HReg src = iselDblExpr(env, e->Iex.Unop.arg);
6522 HReg dst = newVRegD(env);
6523 addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
6524 return dst;
6528 if (e->tag == Iex_Binop) {
6529 switch (e->Iex.Binop.op) {
6530 case Iop_RoundF64toInt: {
6531 HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
6532 HReg dst = newVRegD(env);
6534 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6535 #if (__mips_isa_rev >= 6)
6536 addInstr(env, MIPSInstr_FpConvert(Mfp_RINTD, dst, src));
6537 #else
6538 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, dst, src));
6539 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, dst, dst));
6541 #endif
6542 set_MIPS_rounding_default(env);
6544 return dst;
6547 case Iop_SqrtF64: {
6548 HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
6549 HReg dst = newVRegD(env);
6550 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6551 addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
6552 set_MIPS_rounding_default(env);
6553 return dst;
6556 case Iop_I64StoF64: {
6557 HReg r_dst = newVRegD(env);
6558 MIPSAMode *am_addr;
6559 HReg tmp, fr_src;
6560 if (mode64) {
6561 tmp = newVRegD(env);
6562 fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
6563 /* Move SP down 8 bytes */
6564 sub_from_sp(env, 8);
6565 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6567 /* store as I64 */
6568 addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6570 /* load as Ity_F64 */
6571 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6573 /* Reset SP */
6574 add_to_sp(env, 8);
6575 } else {
6576 HReg Hi, Lo;
6577 tmp = newVRegD(env);
6578 iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6579 tmp = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
6582 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6583 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6584 set_MIPS_rounding_default(env);
6586 return r_dst;
6589 case Iop_I64UtoF64: {
6590 HReg r_dst;
6591 HReg tmp = newVRegV(env);
6592 HReg r_src2h, r_src2l;
6593 vassert(has_msa);
6594 iselInt64Expr(&r_src2h, &r_src2l, env, e->Iex.Binop.arg2);
6595 set_MIPS_rounding_mode_MSA(env, e->Iex.Binop.arg1);
6596 addInstr(env, MIPSInstr_Msa2R(MSA_FILL, MSA_W, r_src2l, tmp));
6597 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2h, tmp, MSA_DFN_W | 1));
6598 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2l, tmp, MSA_DFN_W | 2));
6599 addInstr(env, MIPSInstr_MsaElm(MSA_INSERT, r_src2h, tmp, MSA_DFN_W | 3));
6600 HReg r_srchh = newVRegI(env);
6601 HReg r_srchl = newVRegI(env);
6602 addInstr(env, MIPSInstr_Msa2RF(MSA_FFINT_U, MSA_F_DW, tmp, tmp));
6603 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srchl, MSA_DFN_W | 0));
6604 addInstr(env, MIPSInstr_MsaElm(MSA_COPY_S, tmp, r_srchh, MSA_DFN_W | 1));
6605 r_dst = mk_LoadRR32toFPR(env, r_srchh, r_srchl);
6606 set_MIPS_rounding_default_MSA(env);
6607 return r_dst;
6609 #if (__mips_isa_rev >= 6)
6610 case Iop_MaxNumF64: {
6611 HReg src1 = iselDblExpr(env, e->Iex.Binop.arg1);
6612 HReg src2 = iselDblExpr(env, e->Iex.Binop.arg2);
6613 HReg dst = newVRegD(env);
6614 addInstr(env, MIPSInstr_FpMinMax(Mfp_MAXD, dst,
6615 src1, src2));
6616 return dst;
6619 case Iop_MinNumF64: {
6620 HReg src1 = iselDblExpr(env, e->Iex.Binop.arg1);
6621 HReg src2 = iselDblExpr(env, e->Iex.Binop.arg2);
6622 HReg dst = newVRegD(env);
6623 addInstr(env, MIPSInstr_FpMinMax(Mfp_MIND, dst,
6624 src1, src2));
6625 return dst;
6627 #endif
6629 default:
6630 break;
6635 if (e->tag == Iex_Triop) {
6636 switch (e->Iex.Triop.details->op) {
6637 case Iop_DivF64:
6638 case Iop_DivF32:
6639 case Iop_MulF64:
6640 case Iop_AddF64:
6641 case Iop_SubF64: {
6642 MIPSFpOp op = 0;
6643 HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
6644 HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
6645 HReg dst = newVRegD(env);
6646 switch (e->Iex.Triop.details->op) {
6647 case Iop_DivF64:
6648 op = Mfp_DIVD;
6649 break;
6650 case Iop_DivF32:
6651 op = Mfp_DIVS;
6652 break;
6653 case Iop_MulF64:
6654 op = Mfp_MULD;
6655 break;
6656 case Iop_AddF64:
6657 op = Mfp_ADDD;
6658 break;
6659 case Iop_SubF64:
6660 op = Mfp_SUBD;
6661 break;
6662 default:
6663 vassert(0);
6665 set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
6666 addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
6667 set_MIPS_rounding_default(env);
6668 return dst;
6671 case Iop_ScaleF64: {
6672 HReg src1 = iselDblExpr(env, e->Iex.Triop.details->arg2);
6673 HReg src2 = iselDblExpr(env, e->Iex.Triop.details->arg3);
6674 HReg v_help = newVRegV(env);
6675 HReg dst = newVRegD(env);
6676 vassert(has_msa);
6677 set_MIPS_rounding_mode_MSA(env, e->Iex.Triop.details->arg1);
6678 addInstr(env, MIPSInstr_Msa2RF(MSA_FTINT_S, MSA_F_DW, v_help, src2));
6679 addInstr(env, MIPSInstr_Msa3RF(MSA_FEXP2, MSA_F_DW, dst, src1, v_help));
6680 set_MIPS_rounding_default_MSA(env);
6681 return dst;
6683 default:
6684 break;
6688 if (e->tag == Iex_Qop) {
6689 switch (e->Iex.Qop.details->op) {
6690 case Iop_MAddF64:
6691 case Iop_MSubF64: {
6692 MSA3RFOp op = 0;
6693 switch (e->Iex.Qop.details->op) {
6694 #if (__mips_isa_rev >= 6)
6695 case Iop_MAddF64:
6696 op = Mfp_MADDD;
6697 break;
6698 case Iop_MSubF64:
6699 op = Mfp_MSUBD;
6700 break;
6701 #else
6702 case Iop_MAddF64:
6703 op = MSA_FMADD;
6704 break;
6705 case Iop_MSubF64:
6706 op = MSA_FMSUB;
6707 break;
6708 #endif
6709 default:
6710 vassert(0);
6712 HReg dst = newVRegD(env);
6713 HReg src1 = iselDblExpr(env, e->Iex.Qop.details->arg2);
6714 HReg src2 = iselDblExpr(env, e->Iex.Qop.details->arg3);
6715 HReg src3 = iselDblExpr(env, e->Iex.Qop.details->arg4);
6716 #if (__mips_isa_rev >= 6)
6717 set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
6718 addInstr(env, MIPSInstr_FpTernary(op, dst,
6719 src3, src1, src2));
6720 set_MIPS_rounding_default(env);
6721 #else
6722 vassert(has_msa);
6723 addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, src3, dst, 0));
6724 set_MIPS_rounding_mode_MSA(env, e->Iex.Qop.details->arg1);
6725 addInstr(env, MIPSInstr_Msa3RF(op, MSA_F_DW, dst, src1, src2));
6726 set_MIPS_rounding_default_MSA(env);
6727 #endif
6728 return dst;
6730 case Iop_I64StoF64: {
6731 HReg r_dst = newVRegD(env);
6732 MIPSAMode *am_addr;
6733 HReg tmp, fr_src;
6734 if (mode64) {
6735 tmp = newVRegF(env);
6736 fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
6737 /* Move SP down 8 bytes */
6738 sub_from_sp(env, 8);
6739 am_addr = MIPSAMode_IR(0, StackPointer(mode64));
6741 /* store as I64 */
6742 addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
6744 /* load as Ity_F64 */
6745 addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
6747 /* Reset SP */
6748 add_to_sp(env, 8);
6749 } else {
6750 HReg Hi, Lo;
6751 tmp = newVRegD(env);
6752 iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
6753 tmp = mk_LoadRR32toFPR(env, Hi, Lo); /* 2*I32 -> F64 */
6756 set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
6757 addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
6758 set_MIPS_rounding_default(env);
6760 return r_dst;
6763 default:
6764 break;
6768 /* --------- ITE --------- */
6769 if (e->tag == Iex_ITE) {
6770 if (ty == Ity_F64
6771 && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
6772 HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse);
6773 HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue);
6774 HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
6775 HReg r_dst = newVRegD(env);
6776 #if (__mips_isa_rev >= 6)
6777 addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, r_cond));
6778 addInstr(env, MIPSInstr_MoveCond(MFpSeld, r_dst, r0, r1));
6779 #else
6780 addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
6781 addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
6782 r_cond));
6783 #endif
6784 return r_dst;
6788 vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
6789 ppIRExpr(e);
6790 vpanic("iselDblExpr_wrk(mips)");
6793 /*---------------------------------------------------------*/
6794 /*--- ISEL: Statements ---*/
6795 /*---------------------------------------------------------*/
6797 static void iselStmt(ISelEnv * env, IRStmt * stmt)
6799 if (vex_traceflags & VEX_TRACE_VCODE) {
6800 vex_printf("\n-- ");
6802 ppIRStmt(stmt);
6803 vex_printf("\n");
6806 switch (stmt->tag) {
6807 /* --------- STORE --------- */
6808 case Ist_Store: {
6809 MIPSAMode *am_addr;
6810 IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
6812 if (tyd == Ity_V128) {
6813 vassert(has_msa);
6814 HReg res = iselV128Expr(env, stmt->Ist.Store.data);
6815 HReg addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
6816 addInstr(env, MIPSInstr_MsaMi10(MSA_ST, 0, addr, res, MSA_B));
6817 return;
6820 /*constructs addressing mode from address provided */
6821 am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
6823 if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
6824 (mode64 && (tyd == Ity_I64))) {
6825 HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
6826 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
6827 am_addr, r_src, mode64));
6828 return;
6830 if (!mode64 && (tyd == Ity_I64)) {
6831 HReg vHi, vLo;
6832 HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
6834 iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
6836 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6837 MIPSAMode_IR(0, r_addr), vHi, mode64));
6838 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6839 MIPSAMode_IR(4, r_addr), vLo, mode64));
6840 return;
6842 if (tyd == Ity_F32) {
6843 HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
6844 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
6845 am_addr));
6846 return;
6848 if (tyd == Ity_F64 && mode64) {
6849 HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
6850 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6851 am_addr));
6852 return;
6854 if (!mode64 && (tyd == Ity_F64)) {
6855 HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
6856 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6857 am_addr));
6858 return;
6861 break;
6864 /* --------- PUT --------- */
6865 case Ist_Put: {
6866 IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
6868 if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
6869 (ty == Ity_I64 && mode64)) {
6870 HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
6871 MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6872 GuestStatePointer(mode64));
6873 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
6874 am_addr, r_src, mode64));
6875 return;
6878 if (ty == Ity_I64 && !mode64) {
6879 HReg vHi, vLo;
6880 MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6881 GuestStatePointer(mode64));
6882 MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
6883 GuestStatePointer(mode64));
6884 iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
6885 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6886 am_addr, vLo, mode64));
6887 addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
6888 am_addr4, vHi, mode64));
6889 return;
6893 if (ty == Ity_F32) {
6894 HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
6895 MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6896 GuestStatePointer(mode64));
6897 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
6898 am_addr));
6899 return;
6902 if (ty == Ity_F64) {
6903 if (mode64) {
6904 HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
6905 MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6906 GuestStatePointer(mode64));
6907 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6908 am_addr));
6909 } else {
6910 HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data);
6911 MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
6912 GuestStatePointer(mode64));
6913 addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
6914 am_addr));
6916 return;
6918 if (ty == Ity_V128) {
6919 vassert(has_msa);
6920 HReg v_src = iselV128Expr(env, stmt->Ist.Put.data);
6921 #if defined(_MIPSEB)
6922 HReg r_addr = newVRegI(env);
6923 addInstr(env, MIPSInstr_Alu(mode64 ? Malu_DADD : Malu_ADD, r_addr, GuestStatePointer(mode64),
6924 MIPSRH_Imm(False, stmt->Ist.Put.offset)));
6925 addInstr(env, MIPSInstr_MsaMi10(MSA_ST, 0, r_addr, v_src, MSA_B));
6926 #else
6927 vassert(!(stmt->Ist.Put.offset & 7));
6928 addInstr(env, MIPSInstr_MsaMi10(MSA_ST, stmt->Ist.Put.offset >> 3,
6929 GuestStatePointer(mode64), v_src, MSA_D));
6930 #endif
6931 return;
6933 break;
6936 /* --------- TMP --------- */
6937 case Ist_WrTmp: {
6938 IRTemp tmp = stmt->Ist.WrTmp.tmp;
6939 IRType ty = typeOfIRTemp(env->type_env, tmp);
6941 if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
6942 HReg r_dst = lookupIRTemp(env, tmp);
6943 HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
6944 addInstr(env, mk_iMOVds_RR(r_dst, r_src));
6945 return;
6948 if (ty == Ity_I64) {
6949 if (mode64) {
6950 HReg r_dst = lookupIRTemp(env, tmp);
6951 HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
6952 addInstr(env, mk_iMOVds_RR(r_dst, r_src));
6953 return;
6954 } else {
6955 HReg rHi, rLo, dstHi, dstLo;
6956 iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
6957 lookupIRTemp64(&dstHi, &dstLo, env, tmp);
6958 addInstr(env, mk_iMOVds_RR(dstHi, rHi));
6959 addInstr(env, mk_iMOVds_RR(dstLo, rLo));
6960 return;
6964 if (mode64 && ty == Ity_I128) {
6965 HReg rHi, rLo, dstHi, dstLo;
6966 iselInt128Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
6967 lookupIRTempPair(&dstHi, &dstLo, env, tmp);
6968 addInstr(env, mk_iMOVds_RR(dstHi, rHi));
6969 addInstr(env, mk_iMOVds_RR(dstLo, rLo));
6970 return;
6973 if (ty == Ity_F32) {
6974 HReg fr_dst = lookupIRTemp(env, tmp);
6975 HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
6976 addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
6977 return;
6980 if (ty == Ity_F64) {
6981 if (mode64) {
6982 HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
6983 HReg dst = lookupIRTemp(env, tmp);
6984 addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
6985 return;
6986 } else {
6987 HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
6988 HReg dst = lookupIRTemp(env, tmp);
6989 addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
6990 return;
6994 if (ty == Ity_V128) {
6995 vassert(has_msa);
6996 HReg v_dst = lookupIRTemp(env, tmp);
6997 HReg v_src = iselV128Expr(env, stmt->Ist.WrTmp.data);
6998 addInstr(env, MIPSInstr_MsaElm(MSA_MOVE, v_src, v_dst, 0));
6999 return;
7001 break;
7004 /* --------- Call to DIRTY helper --------- */
7005 case Ist_Dirty: {
7006 IRDirty *d = stmt->Ist.Dirty.details;
7008 /* Figure out the return type, if any. */
7009 IRType retty = Ity_INVALID;
7010 if (d->tmp != IRTemp_INVALID)
7011 retty = typeOfIRTemp(env->type_env, d->tmp);
7013 /* Throw out any return types we don't know about. */
7014 Bool retty_ok = False;
7015 switch (retty) {
7016 case Ity_INVALID: /* Function doesn't return anything. */
7017 case Ity_V128:
7018 case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
7019 retty_ok = True; break;
7020 default:
7021 break;
7024 if (!retty_ok)
7025 break; /* will go to stmt_fail: */
7027 /* Marshal args, do the call, clear stack, set the return value
7028 to 0x555..555 if this is a conditional call that returns a
7029 value and the call is skipped. */
7030 UInt addToSp = 0;
7031 RetLoc rloc = mk_RetLoc_INVALID();
7032 doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args );
7033 vassert(is_sane_RetLoc(rloc));
7035 /* Now figure out what to do with the returned value, if any. */
7036 switch (retty) {
7037 case Ity_INVALID: {
7038 /* No return value. Nothing to do. */
7039 vassert(d->tmp == IRTemp_INVALID);
7040 vassert(rloc.pri == RLPri_None);
7041 vassert(addToSp == 0);
7042 return;
7044 case Ity_I32: case Ity_I16: case Ity_I8: {
7045 /* The returned value is in $v0. Park it in the register
7046 associated with tmp. */
7047 HReg r_dst = lookupIRTemp(env, d->tmp);
7048 addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_dst,
7049 hregMIPS_GPR2(mode64),
7050 MIPSRH_Imm(False, 0)));
7051 vassert(rloc.pri == RLPri_Int);
7052 vassert(addToSp == 0);
7053 return;
7055 case Ity_I64: {
7056 if (mode64) {
7057 /* The returned value is in $v0. Park it in the register
7058 associated with tmp. */
7059 HReg r_dst = lookupIRTemp(env, d->tmp);
7060 addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
7061 vassert(rloc.pri == RLPri_Int);
7062 vassert(addToSp == 0);
7063 return;
7064 } else {
7065 HReg rHi = newVRegI(env);
7066 HReg rLo = newVRegI(env);
7067 HReg dstHi, dstLo;
7068 addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64)));
7069 addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64)));
7070 lookupIRTemp64(&dstHi, &dstLo, env, d->tmp);
7071 addInstr(env, mk_iMOVds_RR(dstHi, rHi));
7072 addInstr(env, mk_iMOVds_RR(dstLo, rLo));
7073 return;
7076 case Ity_V128: {
7077 vassert(has_msa);
7078 vassert(rloc.pri == RLPri_V128SpRel);
7079 vassert((rloc.spOff < 512) && (rloc.spOff > -512));
7080 vassert(addToSp >= 16);
7081 HReg dst = lookupIRTemp(env, d->tmp);
7082 addInstr(env, MIPSInstr_MsaMi10(MSA_LD, rloc.spOff, StackPointer(mode64), dst, MSA_B));
7083 add_to_sp(env, addToSp);
7084 return;
7087 default:
7088 /*NOTREACHED*/
7089 vassert(0);
7093 /* --------- Load Linked or Store Conditional --------- */
7094 case Ist_LLSC: {
7095 /* Temporary solution; this need to be rewritten again for MIPS.
7096 On MIPS you can not read from address that is locked with LL
7097 before SC. If you read from address that is locked than SC will
7098 fall. */
7099 IRTemp res = stmt->Ist.LLSC.result;
7100 IRType tyRes = typeOfIRTemp(env->type_env, res);
7101 IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
7103 if (!mode64 && (tyAddr != Ity_I32))
7104 goto stmt_fail;
7106 if (stmt->Ist.LLSC.storedata == NULL) {
7107 /* LL */
7108 MIPSAMode *r_addr;
7109 /* constructs addressing mode from address provided */
7110 r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
7112 HReg r_dst = lookupIRTemp(env, res);
7113 if (tyRes == Ity_I32) {
7114 addInstr(env, MIPSInstr_LoadL(4, r_dst, r_addr, mode64));
7115 return;
7116 } else if (tyRes == Ity_I64 && mode64) {
7117 addInstr(env, MIPSInstr_LoadL(8, r_dst, r_addr, mode64));
7118 return;
7120 } else {
7121 /* SC */
7122 MIPSAMode *r_addr;
7123 r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
7124 HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
7125 HReg r_dst = lookupIRTemp(env, res);
7126 IRType tyData = typeOfIRExpr(env->type_env,
7127 stmt->Ist.LLSC.storedata);
7129 if (tyData == Ity_I32) {
7130 addInstr(env, mk_iMOVds_RR(r_dst, r_src));
7131 addInstr(env, MIPSInstr_StoreC(4, r_addr, r_dst, mode64));
7132 return;
7133 } else if (tyData == Ity_I64 && mode64) {
7134 addInstr(env, mk_iMOVds_RR(r_dst, r_src));
7135 addInstr(env, MIPSInstr_StoreC(8, r_addr, r_dst, mode64));
7136 return;
7139 goto stmt_fail;
7140 /* NOTREACHED */}
7142 case Ist_CAS:
7143 if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
7144 IRCAS *cas = stmt->Ist.CAS.details;
7145 HReg old = lookupIRTemp(env, cas->oldLo);
7146 HReg addr = iselWordExpr_R(env, cas->addr);
7147 HReg expd = iselWordExpr_R(env, cas->expdLo);
7148 HReg data = iselWordExpr_R(env, cas->dataLo);
7149 if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I64) {
7150 addInstr(env, MIPSInstr_Cas(8, old, addr, expd, data, mode64));
7151 } else if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
7152 addInstr(env, MIPSInstr_Cas(4, old, addr, expd, data, mode64));
7155 return;
7157 /* --------- INSTR MARK --------- */
7158 /* Doesn't generate any executable code ... */
7159 case Ist_IMark:
7160 return;
7162 /* --------- ABI HINT --------- */
7163 /* These have no meaning (denotation in the IR) and so we ignore
7164 them ... if any actually made it this far. */
7165 case Ist_AbiHint:
7166 return;
7168 /* --------- NO-OP --------- */
7169 /* Fairly self-explanatory, wouldn't you say? */
7170 case Ist_NoOp:
7171 return;
7173 /* --------- EXIT --------- */
7174 case Ist_Exit: {
7175 IRConst* dst = stmt->Ist.Exit.dst;
7176 if (!mode64 && dst->tag != Ico_U32)
7177 vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
7178 if (mode64 && dst->tag != Ico_U64)
7179 vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
7181 MIPSCondCode cc = iselCondCode(env, stmt->Ist.Exit.guard);
7182 MIPSAMode* amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
7183 GuestStatePointer(mode64));
7185 /* Case: boring transfer to known address */
7186 if (stmt->Ist.Exit.jk == Ijk_Boring
7187 || stmt->Ist.Exit.jk == Ijk_Call
7188 /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
7189 if (env->chainingAllowed) {
7190 /* .. almost always true .. */
7191 /* Skip the event check at the dst if this is a forwards
7192 edge. */
7193 Bool toFastEP
7194 = mode64
7195 ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
7196 : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
7197 if (0) vex_printf("%s", toFastEP ? "Y" : ",");
7198 addInstr(env, MIPSInstr_XDirect(
7199 mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
7200 : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
7201 amPC, cc, toFastEP));
7202 } else {
7203 /* .. very occasionally .. */
7204 /* We can't use chaining, so ask for an assisted transfer,
7205 as that's the only alternative that is allowable. */
7206 HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
7207 addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
7209 return;
7212 /* Case: assisted transfer to arbitrary address */
7213 switch (stmt->Ist.Exit.jk) {
7214 /* Keep this list in sync with that in iselNext below */
7215 case Ijk_ClientReq:
7216 case Ijk_EmFail:
7217 case Ijk_EmWarn:
7218 case Ijk_NoDecode:
7219 case Ijk_NoRedir:
7220 case Ijk_SigBUS:
7221 case Ijk_Yield:
7222 case Ijk_SigTRAP:
7223 case Ijk_SigFPE_IntDiv:
7224 case Ijk_SigFPE_IntOvf:
7225 case Ijk_Sys_syscall:
7226 case Ijk_InvalICache:
7228 HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
7229 addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
7230 stmt->Ist.Exit.jk));
7231 return;
7233 default:
7234 break;
7237 /* Do we ever expect to see any other kind? */
7238 goto stmt_fail;
7241 default:
7242 break;
7245 stmt_fail:
7246 vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
7247 ppIRStmt(stmt);
7248 vpanic("iselStmt:\n");
7251 /*---------------------------------------------------------*/
7252 /*--- ISEL: Basic block terminators (Nexts) ---*/
7253 /*---------------------------------------------------------*/
7255 static void iselNext ( ISelEnv* env,
7256 IRExpr* next, IRJumpKind jk, Int offsIP )
7258 if (vex_traceflags & VEX_TRACE_VCODE) {
7259 vex_printf( "\n-- PUT(%d) = ", offsIP);
7260 ppIRExpr( next );
7261 vex_printf( "; exit-");
7262 ppIRJumpKind(jk);
7263 vex_printf( "\n");
7266 /* Case: boring transfer to known address */
7267 if (next->tag == Iex_Const) {
7268 IRConst* cdst = next->Iex.Const.con;
7269 vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
7270 if (jk == Ijk_Boring || jk == Ijk_Call) {
7271 /* Boring transfer to known address */
7272 MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
7273 if (env->chainingAllowed) {
7274 /* .. almost always true .. */
7275 /* Skip the event check at the dst if this is a forwards
7276 edge. */
7277 Bool toFastEP
7278 = env->mode64
7279 ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
7280 : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
7281 if (0) vex_printf("%s", toFastEP ? "X" : ".");
7282 addInstr(env, MIPSInstr_XDirect(
7283 env->mode64 ? (Addr64)cdst->Ico.U64
7284 : (Addr64)cdst->Ico.U32,
7285 amPC, MIPScc_AL, toFastEP));
7286 } else {
7287 /* .. very occasionally .. */
7288 /* We can't use chaining, so ask for an assisted transfer,
7289 as that's the only alternative that is allowable. */
7290 HReg r = iselWordExpr_R(env, next);
7291 addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
7292 Ijk_Boring));
7294 return;
7298 /* Case: call/return (==boring) transfer to any address */
7299 switch (jk) {
7300 case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
7301 HReg r = iselWordExpr_R(env, next);
7302 MIPSAMode* amPC = MIPSAMode_IR(offsIP,
7303 GuestStatePointer(env->mode64));
7304 if (env->chainingAllowed) {
7305 addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
7306 } else {
7307 addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
7308 Ijk_Boring));
7310 return;
7312 default:
7313 break;
7316 /* Case: assisted transfer to arbitrary address */
7317 switch (jk) {
7318 /* Keep this list in sync with that for Ist_Exit above */
7319 case Ijk_ClientReq:
7320 case Ijk_EmFail:
7321 case Ijk_EmWarn:
7322 case Ijk_NoDecode:
7323 case Ijk_NoRedir:
7324 case Ijk_SigBUS:
7325 case Ijk_SigILL:
7326 case Ijk_SigTRAP:
7327 case Ijk_SigFPE_IntDiv:
7328 case Ijk_SigFPE_IntOvf:
7329 case Ijk_Sys_syscall:
7330 case Ijk_InvalICache: {
7331 HReg r = iselWordExpr_R(env, next);
7332 MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
7333 addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
7334 return;
7336 default:
7337 break;
7340 vex_printf("\n-- PUT(%d) = ", offsIP);
7341 ppIRExpr(next );
7342 vex_printf("; exit-");
7343 ppIRJumpKind(jk);
7344 vex_printf("\n");
7345 vassert(0); /* are we expecting any other kind? */
7348 /*---------------------------------------------------------*/
7349 /*--- Insn selector top-level ---*/
7350 /*---------------------------------------------------------*/
7352 /* Translate an entire BB to mips code. */
7353 HInstrArray *iselSB_MIPS ( const IRSB* bb,
7354 VexArch arch_host,
7355 const VexArchInfo* archinfo_host,
7356 const VexAbiInfo* vbi,
7357 Int offs_Host_EvC_Counter,
7358 Int offs_Host_EvC_FailAddr,
7359 Bool chainingAllowed,
7360 Bool addProfInc,
7361 Addr max_ga )
7363 Int i, j;
7364 HReg hreg, hregHI;
7365 ISelEnv* env;
7366 MIPSAMode *amCounter, *amFailAddr;
7368 hwcaps_host = archinfo_host->hwcaps;
7370 /* sanity ... */
7371 vassert(arch_host == VexArchMIPS32 || arch_host == VexArchMIPS64);
7372 vassert(VEX_PRID_COMP_MIPS == VEX_MIPS_COMP_ID(hwcaps_host)
7373 || VEX_PRID_COMP_CAVIUM == VEX_MIPS_COMP_ID(hwcaps_host)
7374 || VEX_PRID_COMP_BROADCOM == VEX_MIPS_COMP_ID(hwcaps_host)
7375 || VEX_PRID_COMP_NETLOGIC == VEX_MIPS_COMP_ID(hwcaps_host)
7376 || VEX_PRID_COMP_INGENIC_E1 == VEX_MIPS_COMP_ID(hwcaps_host)
7377 || VEX_PRID_COMP_LEGACY == VEX_MIPS_COMP_ID(hwcaps_host));
7379 /* Check that the host's endianness is as expected. */
7380 vassert(archinfo_host->endness == VexEndnessLE
7381 || archinfo_host->endness == VexEndnessBE);
7383 mode64 = arch_host != VexArchMIPS32;
7384 fp_mode64 = VEX_MIPS_HOST_FP_MODE(hwcaps_host);
7385 has_msa = VEX_MIPS_PROC_MSA(archinfo_host->hwcaps);
7387 /* Make up an initial environment to use. */
7388 env = LibVEX_Alloc_inline(sizeof(ISelEnv));
7389 env->vreg_ctr = 0;
7390 env->mode64 = mode64;
7391 env->fp_mode64 = fp_mode64;
7393 /* Set up output code array. */
7394 env->code = newHInstrArray();
7396 /* Copy BB's type env. */
7397 env->type_env = bb->tyenv;
7399 /* Make up an IRTemp -> virtual HReg mapping. This doesn't
7400 change as we go along. */
7401 env->n_vregmap = bb->tyenv->types_used;
7402 env->vregmap = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7403 env->vregmapHI = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7405 /* and finally ... */
7406 env->hwcaps = hwcaps_host;
7407 env->chainingAllowed = chainingAllowed;
7408 env->hwcaps = hwcaps_host;
7409 env->max_ga = max_ga;
7411 /* For each IR temporary, allocate a suitably-kinded virtual
7412 register. */
7413 j = 0;
7414 for (i = 0; i < env->n_vregmap; i++) {
7415 hregHI = hreg = INVALID_HREG;
7416 switch (bb->tyenv->types[i]) {
7417 case Ity_I1:
7418 case Ity_I8:
7419 case Ity_I16:
7420 case Ity_I32:
7421 if (mode64) {
7422 hreg = mkHReg(True, HRcInt64, 0, j++);
7423 break;
7424 } else {
7425 hreg = mkHReg(True, HRcInt32, 0, j++);
7426 break;
7428 case Ity_I64:
7429 if (mode64) {
7430 hreg = mkHReg(True, HRcInt64, 0, j++);
7431 break;
7432 } else {
7433 hreg = mkHReg(True, HRcInt32, 0, j++);
7434 hregHI = mkHReg(True, HRcInt32, 0, j++);
7435 break;
7437 case Ity_I128:
7438 vassert(mode64);
7439 hreg = mkHReg(True, HRcInt64, 0, j++);
7440 hregHI = mkHReg(True, HRcInt64, 0, j++);
7441 break;
7442 case Ity_F32:
7443 if (mode64) {
7444 hreg = mkHReg(True, HRcFlt64, 0, j++);
7445 break;
7446 } else {
7447 hreg = mkHReg(True, HRcFlt32, 0, j++);
7448 break;
7450 case Ity_F64:
7451 hreg = mkHReg(True, HRcFlt64, 0, j++);
7452 break;
7453 case Ity_V128:
7454 hreg = mkHReg(True, HRcVec128, 0, j++);
7455 break;
7456 default:
7457 ppIRType(bb->tyenv->types[i]);
7458 vpanic("iselBB(mips): IRTemp type");
7459 break;
7461 env->vregmap[i] = hreg;
7462 env->vregmapHI[i] = hregHI;
7464 env->vreg_ctr = j;
7466 /* The very first instruction must be an event check. */
7467 amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, GuestStatePointer(mode64));
7468 amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, GuestStatePointer(mode64));
7469 addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
7471 /* Possibly a block counter increment (for profiling). At this
7472 point we don't know the address of the counter, so just pretend
7473 it is zero. It will have to be patched later, but before this
7474 translation is used, by a call to LibVEX_patchProfCtr. */
7475 if (addProfInc) {
7476 addInstr(env, MIPSInstr_ProfInc());
7479 /* Ok, finally we can iterate over the statements. */
7480 for (i = 0; i < bb->stmts_used; i++)
7481 iselStmt(env, bb->stmts[i]);
7483 iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
7485 /* record the number of vregs we used. */
7486 env->code->n_vregs = env->vreg_ctr;
7487 return env->code;
7491 /*---------------------------------------------------------------*/
7492 /*--- end host_mips_isel.c ---*/
7493 /*---------------------------------------------------------------*/