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