2 /*---------------------------------------------------------------*/
3 /*--- begin host_mips_isel.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2010-2017 RT-RK
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, see <http://www.gnu.org/licenses/>.
25 The GNU General Public License is contained in the file COPYING.
28 #include "libvex_basictypes.h"
29 #include "libvex_ir.h"
32 #include "main_util.h"
33 #include "main_globals.h"
34 #include "host_generic_regs.h"
35 #include "host_generic_simd64.h" /* for 64-bit SIMD helpers */
36 #include "host_mips_defs.h"
38 /*---------------------------------------------------------*/
39 /*--- Register Usage Conventions ---*/
40 /*---------------------------------------------------------*/
50 static Bool mode64
= False
;
52 /* Host CPU has FPU and 32 dbl. prec. FP registers. */
53 static Bool fp_mode64
= False
;
56 static UInt hwcaps_host
= 0;
58 /* Host CPU has MSA ASE */
59 static Bool has_msa
= False
;
61 /* GPR register class for mips32/64 */
62 #define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
64 /* FPR register class for mips32/64 */
65 #define HRcFPR(_mode64) ((_mode64) ? HRcFlt64 : HRcFlt32)
67 /*---------------------------------------------------------*/
69 /*---------------------------------------------------------*/
71 /* This carries around:
73 - A mapping from IRTemp to IRType, giving the type of any IRTemp we
74 might encounter. This is computed before insn selection starts,
77 - A mapping from IRTemp to HReg. This tells the insn selector
78 which virtual register(s) are associated with each IRTemp
79 temporary. This is computed before insn selection starts, and
80 does not change. We expect this mapping to map precisely the
81 same set of IRTemps as the type mapping does.
83 - vregmap holds the primary register for the IRTemp.
84 - vregmapHI is only used for 64-bit integer-typed
85 IRTemps. It holds the identity of a second
86 32-bit virtual HReg, which holds the high half
89 - The code array, that is, the insns selected so far.
91 - A counter, for generating new virtual registers.
93 - The host subarchitecture we are selecting insns for.
94 This is set at the start and does not change.
96 - A Bool for indicating whether we may generate chain-me
97 instructions for control flow transfers, or whether we must use
100 - The maximum guest address of any guest insn in this block.
101 Actually, the address of the highest-addressed byte from any insn
102 in this block. Is set at the start and does not change. This is
103 used for detecting jumps which are definitely forward-edges from
104 this block, and therefore can be made (chained) to the fast entry
105 point of the destination, thereby avoiding the destination's
108 Note, this is all (well, mostly) host-independent.
113 /* Constant -- are set at the start and do not change. */
124 Bool chainingAllowed
;
127 /* These are modified as we go along. */
133 static HReg
lookupIRTemp(ISelEnv
* env
, IRTemp tmp
)
135 vassert(tmp
< env
->n_vregmap
);
136 return env
->vregmap
[tmp
];
139 static void lookupIRTemp64(HReg
* vrHI
, HReg
* vrLO
, ISelEnv
* env
, IRTemp tmp
)
141 vassert(tmp
< env
->n_vregmap
);
142 vassert(! hregIsInvalid(env
->vregmapHI
[tmp
]));
143 *vrLO
= env
->vregmap
[tmp
];
144 *vrHI
= env
->vregmapHI
[tmp
];
148 lookupIRTempPair(HReg
* vrHI
, HReg
* vrLO
, ISelEnv
* env
, IRTemp tmp
)
150 vassert(env
->mode64
);
151 vassert(tmp
< env
->n_vregmap
);
152 vassert(! hregIsInvalid(env
->vregmapHI
[tmp
]));
153 *vrLO
= env
->vregmap
[tmp
];
154 *vrHI
= env
->vregmapHI
[tmp
];
157 static void addInstr(ISelEnv
* env
, MIPSInstr
* instr
)
159 addHInstr(env
->code
, instr
);
160 if (vex_traceflags
& VEX_TRACE_VCODE
) {
161 ppMIPSInstr(instr
, mode64
);
166 static HReg
newVRegI(ISelEnv
* env
)
168 HReg reg
= mkHReg(True
/*virtual reg*/,
169 HRcGPR(env
->mode64
), 0/*enc*/, env
->vreg_ctr
);
174 static HReg
newVRegD(ISelEnv
* env
)
176 HReg reg
= mkHReg(True
/*virtual reg*/,
177 HRcFlt64
, 0/*enc*/, env
->vreg_ctr
);
182 static HReg
newVRegF(ISelEnv
* env
)
184 HReg reg
= mkHReg(True
/*virtual reg*/,
185 HRcFPR(env
->mode64
), 0/*enc*/, env
->vreg_ctr
);
190 static HReg
newVRegV ( ISelEnv
* env
)
192 HReg reg
= mkHReg(True
/*virtual reg*/, HRcVec128
, 0, env
->vreg_ctr
);
197 static void add_to_sp(ISelEnv
* env
, UInt n
)
199 HReg sp
= StackPointer(mode64
);
200 vassert(n
< 256 && (n
% 8) == 0);
202 addInstr(env
, MIPSInstr_Alu(Malu_DADD
, sp
, sp
, MIPSRH_Imm(True
,
205 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, sp
, sp
, MIPSRH_Imm(True
,
209 static void sub_from_sp(ISelEnv
* env
, UInt n
)
211 HReg sp
= StackPointer(mode64
);
212 vassert(n
< 256 && (n
% 8) == 0);
214 addInstr(env
, MIPSInstr_Alu(Malu_DSUB
, sp
, sp
,
215 MIPSRH_Imm(True
, toUShort(n
))));
217 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, sp
, sp
,
218 MIPSRH_Imm(True
, toUShort(n
))));
221 /*---------------------------------------------------------*/
222 /*--- ISEL: Forward declarations ---*/
223 /*---------------------------------------------------------*/
225 /* These are organised as iselXXX and iselXXX_wrk pairs. The
226 iselXXX_wrk do the real work, but are not to be called directly.
227 For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
228 checks that all returned registers are virtual. You should not
229 call the _wrk version directly.
231 /* 32-bit mode: Compute an I8/I16/I32 into a RH
232 (reg-or-halfword-immediate).
233 It's important to specify whether the immediate is to be regarded
234 as signed or not. If yes, this will never return -32768 as an
235 immediate; this guaranteed that all signed immediates that are
236 return can have their sign inverted if need be.
238 static MIPSRH
*iselWordExpr_RH_wrk(ISelEnv
* env
, Bool syned
, IRExpr
* e
);
239 static MIPSRH
*iselWordExpr_RH(ISelEnv
* env
, Bool syned
, IRExpr
* e
);
241 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
242 immediate in the range 1 .. 31 inclusive. Used for doing shift amounts. */
243 static MIPSRH
*iselWordExpr_RH5u_wrk(ISelEnv
* env
, IRExpr
* e
);
244 static MIPSRH
*iselWordExpr_RH5u(ISelEnv
* env
, IRExpr
* e
);
246 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
247 immediate in the range 1 .. 63 inclusive. Used for doing shift amounts. */
248 static MIPSRH
*iselWordExpr_RH6u_wrk(ISelEnv
* env
, IRExpr
* e
);
249 static MIPSRH
*iselWordExpr_RH6u(ISelEnv
* env
, IRExpr
* e
);
251 /* Compute an I8 into a reg-or-7-bit-unsigned-immediate, the latter being an
252 immediate in the range 1 .. 127 inclusive. Used for doing shift amounts. */
253 static MIPSRH
*iselWordExpr_RH7u_wrk(ISelEnv
* env
, IRExpr
* e
);
254 static MIPSRH
*iselWordExpr_RH7u(ISelEnv
* env
, IRExpr
* e
);
256 /* compute an I8/I16/I32 into a GPR*/
257 static HReg
iselWordExpr_R_wrk(ISelEnv
* env
, IRExpr
* e
);
258 static HReg
iselWordExpr_R(ISelEnv
* env
, IRExpr
* e
);
260 /* compute an I32 into an AMode. */
261 static MIPSAMode
*iselWordExpr_AMode_wrk(ISelEnv
* env
, IRExpr
* e
,
263 static MIPSAMode
*iselWordExpr_AMode(ISelEnv
* env
, IRExpr
* e
, IRType xferTy
);
265 static void iselInt64Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
,
267 static void iselInt64Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
);
269 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
270 static void iselInt128Expr_wrk(HReg
* rHi
, HReg
* rLo
,
271 ISelEnv
* env
, IRExpr
* e
);
272 static void iselInt128Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
);
274 static HReg
iselV128Expr( ISelEnv
* env
, IRExpr
* e
);
275 static HReg
iselV128Expr_wrk( ISelEnv
* env
, IRExpr
* e
);
277 static MIPSCondCode
iselCondCode_wrk(ISelEnv
* env
, IRExpr
* e
);
278 static MIPSCondCode
iselCondCode(ISelEnv
* env
, IRExpr
* e
);
280 static HReg
iselDblExpr_wrk(ISelEnv
* env
, IRExpr
* e
);
281 static HReg
iselDblExpr(ISelEnv
* env
, IRExpr
* e
);
283 static HReg
iselFltExpr_wrk(ISelEnv
* env
, IRExpr
* e
);
284 static HReg
iselFltExpr(ISelEnv
* env
, IRExpr
* e
);
286 static void set_MIPS_rounding_mode(ISelEnv
* env
, IRExpr
* mode
)
289 rounding mode | MIPS | IR
290 ------------------------
293 to +infinity | 10 | 10
294 to -infinity | 11 | 01
296 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
297 HReg irrm
= iselWordExpr_R(env
, mode
);
298 HReg tmp
= newVRegI(env
);
299 HReg fcsr_old
= newVRegI(env
);
302 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, irrm
,
303 MIPSRH_Imm(False
, 1)));
304 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, tmp
, irrm
, MIPSRH_Reg(tmp
)));
305 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
, MIPSRH_Imm(False
, 3)));
306 /* save old value of FCSR */
307 addInstr(env
, MIPSInstr_MfFCSR(fcsr_old
));
308 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
309 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
311 /* store old FCSR to stack */
312 addInstr(env
, MIPSInstr_Store(4, am_addr
, fcsr_old
, mode64
));
314 /* set new value of FCSR */
315 addInstr(env
, MIPSInstr_MtFCSR(tmp
));
318 static void set_MIPS_rounding_mode_MSA(ISelEnv
* env
, IRExpr
* mode
) {
320 rounding mode | MIPS | IR
321 ------------------------
324 to +infinity | 10 | 10
325 to -infinity | 11 | 01
327 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
328 HReg irrm
= iselWordExpr_R(env
, mode
);
329 HReg tmp
= newVRegI(env
);
330 HReg msacsr_old
= newVRegI(env
);
332 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, irrm
,
333 MIPSRH_Imm(False
, 1)));
334 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, tmp
, irrm
, MIPSRH_Reg(tmp
)));
335 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
, MIPSRH_Imm(False
, 3)));
336 /* save old value of MSACSR */
337 addInstr(env
, MIPSInstr_MsaElm(MSA_CFCMSA
, hregMIPS_GPR0(mode64
), msacsr_old
,
339 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
340 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
341 /* store old MSACSR to stack */
342 addInstr(env
, MIPSInstr_Store(4, am_addr
, msacsr_old
, mode64
));
343 /* set new value of MSACSR */
344 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, tmp
, hregMIPS_GPR0(mode64
),
349 static void set_guest_MIPS_rounding_mode_MSA(ISelEnv
* env
) {
351 rounding mode | MIPS | IR
352 ------------------------
355 to +infinity | 10 | 10
356 to -infinity | 11 | 01
358 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
359 HReg irrm
= newVRegI(env
);
360 HReg msacsr_old
= newVRegI(env
);
362 MIPSAMode
*rm_addr
= MIPSAMode_IR(MSACSR_OFFSET(mode64
),
363 GuestStatePointer(mode64
));
364 addInstr(env
, MIPSInstr_Load(4, irrm
, rm_addr
, mode64
));
365 /* save old value of MSACSR */
366 addInstr(env
, MIPSInstr_MsaElm(MSA_CFCMSA
, hregMIPS_GPR0(mode64
), msacsr_old
,
368 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
369 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
370 /* store old MSACSR to stack */
371 addInstr(env
, MIPSInstr_Store(4, am_addr
, msacsr_old
, mode64
));
372 /* set new value of MSACSR */
373 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, irrm
, hregMIPS_GPR0(mode64
),
378 static void set_MIPS_rounding_default(ISelEnv
* env
)
380 HReg fcsr
= newVRegI(env
);
383 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
385 addInstr(env
, MIPSInstr_Load(4, fcsr
, am_addr
, mode64
));
387 add_to_sp(env
, 8); /* Reset SP */
389 /* set new value of FCSR*/
390 addInstr(env
, MIPSInstr_MtFCSR(fcsr
));
393 static void set_MIPS_rounding_default_MSA(ISelEnv
* env
) {
394 HReg msacsr
= newVRegI(env
);
397 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
398 addInstr(env
, MIPSInstr_Load(4, msacsr
, am_addr
, mode64
));
399 add_to_sp(env
, 8); /* Reset SP */
400 /* set new value of FCSR*/
401 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, msacsr
, hregMIPS_GPR0(mode64
),
405 /*---------------------------------------------------------*/
406 /*--- ISEL: Misc helpers ---*/
407 /*---------------------------------------------------------*/
409 /* Make an int reg-reg move. */
410 static MIPSInstr
*mk_iMOVds_RR(HReg r_dst
, HReg r_src
)
412 vassert(hregClass(r_dst
) == hregClass(r_src
));
413 vassert(hregClass(r_src
) == HRcInt32
|| hregClass(r_src
) == HRcInt64
);
414 return MIPSInstr_Alu(Malu_OR
, r_dst
, r_src
, MIPSRH_Reg(r_src
));
417 /*---------------------------------------------------------*/
418 /*--- ISEL: Function call helpers ---*/
419 /*---------------------------------------------------------*/
421 /* Used only in doHelperCall. See big comment in doHelperCall re
422 handling of register-parameter args. This function figures out
423 whether evaluation of an expression might require use of a fixed
424 register. If in doubt return True (safe but suboptimal).
426 static Bool
mightRequireFixedRegs(IRExpr
* e
)
438 /* Load 2*I32 regs to fp reg */
439 static HReg
mk_LoadRR32toFPR(ISelEnv
* env
, HReg r_srcHi
, HReg r_srcLo
)
441 HReg fr_dst
= newVRegD(env
);
442 MIPSAMode
*am_addr0
, *am_addr1
;
444 vassert(hregClass(r_srcHi
) == HRcInt32
);
445 vassert(hregClass(r_srcLo
) == HRcInt32
);
447 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
448 am_addr0
= MIPSAMode_IR(0, StackPointer(mode64
));
449 am_addr1
= MIPSAMode_IR(4, StackPointer(mode64
));
451 /* store hi,lo as Ity_I32's */
452 #if defined (_MIPSEL)
453 addInstr(env
, MIPSInstr_Store(4, am_addr0
, r_srcLo
, mode64
));
454 addInstr(env
, MIPSInstr_Store(4, am_addr1
, r_srcHi
, mode64
));
455 #elif defined (_MIPSEB)
456 addInstr(env
, MIPSInstr_Store(4, am_addr0
, r_srcHi
, mode64
));
457 addInstr(env
, MIPSInstr_Store(4, am_addr1
, r_srcLo
, mode64
));
459 /* Stop gcc on other platforms complaining about am_addr1 being set
465 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, fr_dst
, am_addr0
));
467 add_to_sp(env
, 16); /* Reset SP */
471 /* Do a complete function call. |guard| is a Ity_Bit expression
472 indicating whether or not the call happens. If guard==NULL, the
473 call is unconditional. |retloc| is set to indicate where the
474 return value is after the call. The caller (of this fn) must
475 generate code to add |stackAdjustAfterCall| to the stack pointer
476 after the call is done. */
478 static void doHelperCall(/*OUT*/UInt
* stackAdjustAfterCall
,
479 /*OUT*/RetLoc
* retloc
,
482 IRCallee
* cee
, IRType retTy
, IRExpr
** args
)
488 Int n_args
, i
, argreg
;
490 HReg src
= INVALID_HREG
;
492 /* Set default returns. We'll update them later if needed. */
493 *stackAdjustAfterCall
= 0;
494 *retloc
= mk_RetLoc_INVALID();
496 /* These are used for cross-checking that IR-level constraints on
497 the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
501 /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
502 are allowed to be used for passing integer arguments. They correspond
503 to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
504 on MIPS host (since we only implement one calling convention) and so we
507 /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
508 are allowed to be used for passing integer arguments. They correspond
509 to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
510 on MIPS host (since we only implement one calling convention) and so we
513 /* The return type can be I{64,32,16,8} or V{128,256}. In the
514 latter two cases, it is expected that |args| will contain the
515 special node IRExpr_VECRET(), in which case this routine
516 generates code to allocate space on the stack for the vector
517 return value. Since we are not passing any scalars on the
518 stack, it is enough to preallocate the return space before
519 marshalling any arguments, in this case.
521 |args| may also contain IRExpr_GSPTR(), in which case the value
522 in the guest state pointer register is passed as the
523 corresponding argument. */
526 for (i
= 0; args
[i
]; i
++) {
527 IRExpr
* arg
= args
[i
];
528 if (UNLIKELY(arg
->tag
== Iex_VECRET
)) {
530 } else if (UNLIKELY(arg
->tag
== Iex_GSPTR
)) {
536 if (n_args
> MIPS_N_REGPARMS
) {
537 vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
540 argregs
[0] = hregMIPS_GPR4(mode64
);
541 argregs
[1] = hregMIPS_GPR5(mode64
);
542 argregs
[2] = hregMIPS_GPR6(mode64
);
543 argregs
[3] = hregMIPS_GPR7(mode64
);
544 argregs
[4] = hregMIPS_GPR8(mode64
);
545 argregs
[5] = hregMIPS_GPR9(mode64
);
546 argregs
[6] = hregMIPS_GPR10(mode64
);
547 argregs
[7] = hregMIPS_GPR11(mode64
);
549 tmpregs
[0] = tmpregs
[1] = tmpregs
[2] =
550 tmpregs
[3] = tmpregs
[4] = tmpregs
[5] =
551 tmpregs
[6] = tmpregs
[7] = INVALID_HREG
;
553 argregs
[0] = hregMIPS_GPR4(mode64
);
554 argregs
[1] = hregMIPS_GPR5(mode64
);
555 argregs
[2] = hregMIPS_GPR6(mode64
);
556 argregs
[3] = hregMIPS_GPR7(mode64
);
558 tmpregs
[0] = tmpregs
[1] = tmpregs
[2] = tmpregs
[3] = INVALID_HREG
;
561 /* First decide which scheme (slow or fast) is to be used. First assume the
562 fast scheme, and select slow if any contraindications (wow) appear. */
566 /* We'll need space on the stack for the return value. Avoid
567 possible complications with nested calls by using the slow
569 if (retTy
== Ity_V128
|| retTy
== Ity_V256
)
572 if (go_fast
&& guard
) {
573 if (guard
->tag
== Iex_Const
&& guard
->Iex
.Const
.con
->tag
== Ico_U1
574 && guard
->Iex
.Const
.con
->Ico
.U1
== True
) {
577 /* Not manifestly unconditional -- be conservative. */
583 for (i
= 0; i
< n_args
; i
++) {
584 if (mightRequireFixedRegs(args
[i
])) {
591 /* At this point the scheme to use has been established. Generate
592 code to get the arg values into the argument rregs. */
597 for (i
= 0; i
< n_args
; i
++) {
598 IRExpr
* arg
= args
[i
];
599 vassert(argreg
< MIPS_N_REGPARMS
);
601 IRType aTy
= Ity_INVALID
;
602 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg
)))
603 aTy
= typeOfIRExpr(env
->type_env
, arg
);
605 if (aTy
== Ity_I32
|| (mode64
&& aTy
!= Ity_INVALID
)) {
606 argiregs
|= (1 << (argreg
+ 4));
607 addInstr(env
, mk_iMOVds_RR(argregs
[argreg
],
608 iselWordExpr_R(env
, arg
)));
610 } else if (aTy
== Ity_I64
) { /* Ity_I64 */
613 argiregs
|= (1 << (argreg
+ 4));
616 iselInt64Expr(&rHi
, &rLo
, env
, arg
);
617 argiregs
|= (1 << (argreg
+ 4));
618 addInstr(env
, mk_iMOVds_RR( argregs
[argreg
++], rLo
));
619 argiregs
|= (1 << (argreg
+ 4));
620 addInstr(env
, mk_iMOVds_RR( argregs
[argreg
], rHi
));
622 } else if (arg
->tag
== Iex_GSPTR
) {
624 addInstr(env
, mk_iMOVds_RR(argregs
[argreg
],
625 GuestStatePointer(mode64
)));
627 } else if (arg
->tag
== Iex_VECRET
) {
628 // If this happens, it denotes ill-formed IR.
632 /* Fast scheme only applies for unconditional calls. Hence: */
635 /* SLOW SCHEME; move via temporaries */
638 for (i
= 0; i
< n_args
; i
++) {
639 vassert(argreg
< MIPS_N_REGPARMS
);
640 IRExpr
* arg
= args
[i
];
642 IRType aTy
= Ity_INVALID
;
643 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg
)))
644 aTy
= typeOfIRExpr(env
->type_env
, arg
);
646 if (aTy
== Ity_I32
|| (mode64
&& aTy
!= Ity_INVALID
)) {
647 tmpregs
[argreg
] = iselWordExpr_R(env
, arg
);
649 } else if (aTy
== Ity_I64
) { /* Ity_I64 */
652 if (argreg
+ 1 >= MIPS_N_REGPARMS
)
653 vassert(0); /* out of argregs */
655 iselInt64Expr(&raHi
, &raLo
, env
, arg
);
656 tmpregs
[argreg
] = raLo
;
658 tmpregs
[argreg
] = raHi
;
660 } else if (arg
->tag
== Iex_GSPTR
) {
661 tmpregs
[argreg
] = GuestStatePointer(mode64
);
664 else if (arg
->tag
== Iex_VECRET
) {
665 tmpregs
[argreg
++] = StackPointer(mode64
);
666 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
670 /* Now we can compute the condition. We can't do it earlier
671 because the argument computations could trash the condition
672 codes. Be a bit clever to handle the common case where the
676 if (guard
->tag
== Iex_Const
&& guard
->Iex
.Const
.con
->tag
== Ico_U1
677 && guard
->Iex
.Const
.con
->Ico
.U1
== True
) {
678 /* unconditional -- do nothing */
680 cc
= iselCondCode(env
, guard
);
681 src
= iselWordExpr_R(env
, guard
);
684 /* Move the args to their final destinations. */
685 for (i
= 0; i
< argreg
; i
++) {
686 if (hregIsInvalid(tmpregs
[i
])) /* Skip invalid regs */
688 /* None of these insns, including any spill code that might
689 be generated, may alter the condition codes. */
690 argiregs
|= (1 << (i
+ 4));
691 addInstr(env
, mk_iMOVds_RR(argregs
[i
], tmpregs
[i
]));
695 /* Do final checks, set the return values, and generate the call
696 instruction proper. */
697 vassert(nGSPTRs
== 0 || nGSPTRs
== 1);
698 vassert(nVECRETs
== ((retTy
== Ity_V128
|| retTy
== Ity_V256
) ? 1 : 0));
699 vassert(*stackAdjustAfterCall
== 0);
700 vassert(is_RetLoc_INVALID(*retloc
));
703 /* Function doesn't return a value. */
704 *retloc
= mk_RetLoc_simple(RLPri_None
);
707 *retloc
= mk_RetLoc_simple(mode64
? RLPri_Int
: RLPri_2Int
);
709 case Ity_I32
: case Ity_I16
: case Ity_I8
:
710 *retloc
= mk_RetLoc_simple(RLPri_Int
);
713 *retloc
= mk_RetLoc_spRel(RLPri_V128SpRel
, 0);
714 *stackAdjustAfterCall
= 16;
718 *retloc
= mk_RetLoc_spRel(RLPri_V256SpRel
, 0);
719 *stackAdjustAfterCall
= 32;
722 /* IR can denote other possible return types, but we don't
723 handle those here. */
727 Addr64 target
= mode64
? (Addr
)cee
->addr
:
728 toUInt((Addr
)cee
->addr
);
730 /* Finally, generate the call itself. This needs the *retloc value
731 set in the switch above, which is why it's at the end. */
733 addInstr(env
, MIPSInstr_CallAlways(cc
, target
, argiregs
,
736 addInstr(env
, MIPSInstr_Call(cc
, target
, argiregs
, src
, *retloc
));
739 /*---------------------------------------------------------*/
740 /*--- ISEL: Integer expression auxiliaries ---*/
741 /*---------------------------------------------------------*/
743 /* --------------------- AMODEs --------------------- */
745 /* Return an AMode which computes the value of the specified
746 expression, possibly also adding insns to the code list as a
747 result. The expression may only be a word-size one.
750 static Bool
uInt_fits_in_16_bits(UInt u
)
755 return toBool(u
== (UInt
) i
);
758 static Bool
uLong_fits_in_16_bits ( ULong u
)
760 Long i
= u
& 0xFFFFULL
;
763 return toBool(u
== (ULong
) i
);
766 static Bool
uLong_is_4_aligned ( ULong u
)
768 return toBool((u
& 3ULL) == 0);
771 static Bool
sane_AMode(ISelEnv
* env
, MIPSAMode
* am
)
775 return toBool(hregClass(am
->Mam
.IR
.base
) == HRcGPR(mode64
) &&
776 hregIsVirtual(am
->Mam
.IR
.base
) &&
777 uInt_fits_in_16_bits(am
->Mam
.IR
.index
));
779 return toBool(hregClass(am
->Mam
.RR
.base
) == HRcGPR(mode64
) &&
780 hregIsVirtual(am
->Mam
.RR
.base
) &&
781 hregClass(am
->Mam
.RR
.index
) == HRcGPR(mode64
) &&
782 hregIsVirtual(am
->Mam
.RR
.index
));
784 vpanic("sane_AMode: unknown mips amode tag");
788 static MIPSAMode
*iselWordExpr_AMode(ISelEnv
* env
, IRExpr
* e
, IRType xferTy
)
790 MIPSAMode
*am
= iselWordExpr_AMode_wrk(env
, e
, xferTy
);
791 vassert(sane_AMode(env
, am
));
795 /* DO NOT CALL THIS DIRECTLY ! */
796 static MIPSAMode
*iselWordExpr_AMode_wrk(ISelEnv
* env
, IRExpr
* e
,
799 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
801 Bool aligned4imm
= toBool(xferTy
== Ity_I32
|| xferTy
== Ity_I64
);
802 vassert(ty
== Ity_I64
);
804 /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
805 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add64
806 && e
->Iex
.Binop
.arg2
->tag
== Iex_Const
807 && e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U64
809 uLong_is_4_aligned(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
) : True
)
810 && uLong_fits_in_16_bits(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
)) {
811 return MIPSAMode_IR((Int
) e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
,
812 iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
));
815 /* Add64(expr,expr) */
816 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add64
) {
817 HReg r_base
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
818 HReg r_idx
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
819 return MIPSAMode_RR(r_idx
, r_base
);
822 vassert(ty
== Ity_I32
);
824 /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
825 if (e
->tag
== Iex_Binop
826 && e
->Iex
.Binop
.op
== Iop_Add32
827 && e
->Iex
.Binop
.arg2
->tag
== Iex_Const
828 && e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U32
829 && uInt_fits_in_16_bits(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
-> Ico
.U32
)) {
830 return MIPSAMode_IR((Int
) e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U32
,
831 iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
));
834 /* Add32(expr,expr) */
835 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add32
) {
836 HReg r_base
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
837 HReg r_idx
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
839 return MIPSAMode_RR(r_idx
, r_base
);
843 /* Doesn't match anything in particular. Generate it into
844 a register and use that. */
845 return MIPSAMode_IR(0, iselWordExpr_R(env
, e
));
848 /*---------------------------------------------------------*/
849 /*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/
850 /*---------------------------------------------------------*/
852 /* Select insns for an integer-typed expression, and add them to the
853 code list. Return a reg holding the result. This reg will be a
854 virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you
855 want to modify it, ask for a new vreg, copy it in there, and modify
856 the copy. The register allocator will do its best to map both
857 vregs to the same real register, so the copies will often disappear
860 This should handle expressions of 64, 32, 16 and 8-bit type.
861 All results are returned in a (mode64 ? 64bit : 32bit) register.
862 For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
863 are arbitrary, so you should mask or sign extend partial values
866 static HReg
iselWordExpr_R(ISelEnv
* env
, IRExpr
* e
)
868 HReg r
= iselWordExpr_R_wrk(env
, e
);
869 /* sanity checks ... */
871 vassert(hregClass(r
) == HRcGPR(env
->mode64
));
872 vassert(hregIsVirtual(r
));
876 /* DO NOT CALL THIS DIRECTLY ! */
877 static HReg
iselWordExpr_R_wrk(ISelEnv
* env
, IRExpr
* e
)
880 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
881 vassert(ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
|| ty
== Ity_I1
882 || ty
== Ity_F32
|| (ty
== Ity_I64
&& mode64
)
883 || (ty
== Ity_I128
&& mode64
));
886 /* --------- TEMP --------- */
888 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
890 /* --------- LOAD --------- */
892 HReg r_dst
= newVRegI(env
);
893 MIPSAMode
*am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
895 if (e
->Iex
.Load
.end
!= Iend_LE
896 && e
->Iex
.Load
.end
!= Iend_BE
)
899 addInstr(env
, MIPSInstr_Load(toUChar(sizeofIRType(ty
)),
900 r_dst
, am_addr
, mode64
));
904 /* --------- BINARY OP --------- */
909 /* Is it an addition or logical style op? */
910 switch (e
->Iex
.Binop
.op
) {
955 aluOp
= Malu_INVALID
;
959 /* For commutative ops we assume any literal
960 values are on the second operand. */
961 if (aluOp
!= Malu_INVALID
) {
962 HReg r_dst
= newVRegI(env
);
963 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
964 MIPSRH
*ri_srcR
= NULL
;
965 /* get right arg into an RH, in the appropriate way */
971 ri_srcR
= iselWordExpr_RH(env
, True
/*signed */ ,
977 ri_srcR
= iselWordExpr_RH(env
, False
/*unsigned */,
981 vpanic("iselWordExpr_R_wrk-aluOp-arg2");
983 addInstr(env
, MIPSInstr_Alu(aluOp
, r_dst
, r_srcL
, ri_srcR
));
988 switch (e
->Iex
.Binop
.op
) {
1004 shftOp
= Mshft_INVALID
;
1008 /* we assume any literal values are on the second operand. */
1009 if (shftOp
!= Mshft_INVALID
) {
1010 HReg r_dst
= newVRegI(env
);
1011 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1014 ri_srcR
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
1016 ri_srcR
= iselWordExpr_RH5u(env
, e
->Iex
.Binop
.arg2
);
1020 } else if (ty
== Ity_I16
) {
1021 if (shftOp
== Mshft_SRA
) {
1022 HReg tmp
= newVRegI(env
);
1023 HReg r_srcL_se
= newVRegI(env
);
1024 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
,
1025 r_srcL
, MIPSRH_Imm(False
, 16)));
1026 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, r_srcL_se
,
1027 tmp
, MIPSRH_Imm(False
, 16)));
1028 addInstr(env
, MIPSInstr_Shft(shftOp
, True
,
1029 r_dst
, r_srcL_se
, ri_srcR
));
1030 } else if (shftOp
== Mshft_SRL
) {
1031 HReg r_srcL_se
= newVRegI(env
);
1032 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcL_se
, r_srcL
,
1033 MIPSRH_Imm(False
, 0xFFFF)));
1034 addInstr(env
, MIPSInstr_Shft(shftOp
, True
,
1035 r_dst
, r_srcL_se
, ri_srcR
));
1039 } else if (ty
== Ity_I32
) {
1040 if (mode64
&& (shftOp
== Mshft_SRA
|| shftOp
== Mshft_SRL
)) {
1041 HReg tmp
= newVRegI(env
);
1042 HReg r_srcL_se
= newVRegI(env
);
1043 /* SRA, SRAV, SRL, SRLV: On 64-bit processors, if GPR rt does
1044 not contain a sign-extended 32-bit value (bits 63..31
1045 equal), then the result of the operation is UNPREDICTABLE.
1046 So we need to sign-extend r_srcL:
1047 DSLLV tmp, r_srcL, 32
1048 DSRAV r_srcL_se, tmp, 32
1050 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tmp
,
1051 r_srcL
, MIPSRH_Imm(False
, 32)));
1052 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
, r_srcL_se
,
1053 tmp
, MIPSRH_Imm(False
, 32)));
1054 /* And finally do the shift. */
1055 addInstr(env
, MIPSInstr_Shft(shftOp
, True
/*32bit shift */,
1056 r_dst
, r_srcL_se
, ri_srcR
));
1058 addInstr(env
, MIPSInstr_Shft(shftOp
, True
/*32bit shift */,
1059 r_dst
, r_srcL
, ri_srcR
));
1060 } else if (ty
== Ity_I64
) {
1062 addInstr(env
, MIPSInstr_Shft(shftOp
, False
/*64bit shift */,
1063 r_dst
, r_srcL
, ri_srcR
));
1069 if (!mode64
&& (e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
1070 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
)) {
1071 HReg tmp1
, tmp2
, tmp3
, tmp4
;
1072 HReg dst1
= newVRegI(env
);
1073 HReg dst2
= newVRegI(env
);
1074 iselInt64Expr(&tmp1
, &tmp2
, env
, e
->Iex
.Binop
.arg1
);
1075 iselInt64Expr(&tmp3
, &tmp4
, env
, e
->Iex
.Binop
.arg2
);
1076 addInstr(env
, MIPSInstr_Cmp(False
, True
, dst1
, tmp1
, tmp3
, MIPScc_EQ
));
1077 addInstr(env
, MIPSInstr_Cmp(False
, True
, dst2
, tmp2
, tmp4
, MIPScc_EQ
));
1078 addInstr(env
, MIPSInstr_Alu(Malu_AND
, dst1
, dst1
, MIPSRH_Reg(dst2
)));
1082 /* Cmp*32*(x,y) ? */
1083 if (e
->Iex
.Binop
.op
== Iop_CmpEQ32
1084 || e
->Iex
.Binop
.op
== Iop_CmpEQ8
1085 || e
->Iex
.Binop
.op
== Iop_CmpEQ16
1086 || e
->Iex
.Binop
.op
== Iop_CmpNE32
1087 || e
->Iex
.Binop
.op
== Iop_CmpNE64
1088 || e
->Iex
.Binop
.op
== Iop_CmpLT32S
1089 || e
->Iex
.Binop
.op
== Iop_CmpLT32U
1090 || e
->Iex
.Binop
.op
== Iop_CmpLT64U
1091 || e
->Iex
.Binop
.op
== Iop_CmpLE32U
1092 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
1093 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
1094 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
1095 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
1096 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ32
1097 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
) {
1099 Bool syned
= (e
->Iex
.Binop
.op
== Iop_CmpLT32S
1100 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
1101 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
1102 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
);
1104 HReg dst
= newVRegI(env
);
1105 HReg r1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1106 HReg r2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1110 switch (e
->Iex
.Binop
.op
) {
1112 case Iop_CasCmpEQ32
:
1158 case Iop_CasCmpEQ64
:
1163 vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
1166 addInstr(env
, MIPSInstr_Cmp(syned
, size32
, dst
, r1
, r2
, cc
));
1170 if (e
->Iex
.Binop
.op
== Iop_Max32U
) {
1171 HReg tmp
= newVRegI(env
);
1172 HReg r_dst
= newVRegI(env
);
1173 HReg argL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1174 HReg argR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1175 MIPSRH
*argRH
= MIPSRH_Reg(argR
);
1181 addInstr(env
, MIPSInstr_Alu(Malu_SLT
, tmp
, argL
, argRH
));
1182 #if (__mips_isa_rev >= 6)
1184 HReg r_temp
= newVRegI(env
);
1185 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dst
, argL
, tmp
));
1186 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, argR
, tmp
));
1187 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
1188 MIPSRH_Reg(r_temp
)));
1192 addInstr(env
, mk_iMOVds_RR(r_dst
, argL
));
1193 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dst
, argR
, tmp
));
1198 if (e
->Iex
.Binop
.op
== Iop_Mul32
) {
1199 HReg r_dst
= newVRegI(env
);
1200 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1201 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1202 #if (__mips_isa_rev >= 6)
1203 addInstr(env
, MIPSInstr_Mulr6(False
, True
, True
,
1204 r_dst
, r_srcL
, r_srcR
));
1206 addInstr(env
, MIPSInstr_Mul(r_dst
, r_srcL
, r_srcR
));
1211 if (e
->Iex
.Binop
.op
== Iop_Mul64
||
1212 e
->Iex
.Binop
.op
== Iop_MullS32
) {
1214 HReg r_dst
= newVRegI(env
);
1215 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1216 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1217 #if (__mips_isa_rev >= 6)
1218 addInstr(env
, MIPSInstr_Mulr6(False
, False
, True
,
1219 r_dst
, r_srcL
, r_srcR
));
1221 addInstr(env
, MIPSInstr_Mult(True
, r_srcL
, r_srcR
));
1222 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1227 if (e
->Iex
.Binop
.op
== Iop_MullU32
) {
1229 HReg r_tmpL
= newVRegI(env
);
1230 HReg r_tmpR
= newVRegI(env
);
1231 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1232 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1233 #if (__mips_isa_rev >= 6)
1234 addInstr(env
, MIPSInstr_Ext(r_tmpL
, r_srcL
, 0, 32));
1235 addInstr(env
, MIPSInstr_Ext(r_tmpR
, r_srcR
, 0, 32));
1236 addInstr(env
, MIPSInstr_Mulr6(True
, False
, True
,
1237 r_tmpR
, r_tmpL
, r_tmpR
));
1239 if (VEX_MIPS_CPU_HAS_MIPS64R2(hwcaps_host
)) {
1240 addInstr(env
, MIPSInstr_Ext(r_tmpL
, r_srcL
, 0, 32));
1241 addInstr(env
, MIPSInstr_Ext(r_tmpR
, r_srcR
, 0, 32));
1243 addInstr(env
, MIPSInstr_LI(r_tmpL
, 0xFFFFFFFF));
1244 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_tmpR
, r_srcR
,
1245 MIPSRH_Reg(r_tmpL
)));
1246 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_tmpL
, r_srcL
,
1247 MIPSRH_Reg(r_tmpL
)));
1249 addInstr(env
, MIPSInstr_Mult(False
, r_tmpL
, r_tmpR
));
1250 addInstr(env
, MIPSInstr_Mflo(r_tmpR
));
1255 if (e
->Iex
.Binop
.op
== Iop_MullU8
||
1256 e
->Iex
.Binop
.op
== Iop_MullS8
||
1257 e
->Iex
.Binop
.op
== Iop_MullU16
||
1258 e
->Iex
.Binop
.op
== Iop_MullS16
) {
1259 Bool syned
= toBool((e
->Iex
.Binop
.op
== Iop_MullS8
) ||
1260 (e
->Iex
.Binop
.op
== Iop_MullS16
));
1261 HReg r_dst
= newVRegI(env
);
1262 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1263 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1264 #if (__mips_isa_rev >= 6)
1266 Int no_bits
= (e
->Iex
.Binop
.op
== Iop_MullS16
) ? 16 : 24;
1267 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1269 MIPSRH_Imm(False
, no_bits
)));
1270 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1272 MIPSRH_Imm(False
, no_bits
)));
1273 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1275 MIPSRH_Imm(False
, no_bits
)));
1276 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1278 MIPSRH_Imm(False
, no_bits
)));
1280 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, True
,
1281 r_dst
, r_srcL
, r_srcR
));
1284 Int no_bits
= (e
->Iex
.Binop
.op
== Iop_MullS16
) ? 16 : 24;
1285 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1287 MIPSRH_Imm(False
, no_bits
)));
1288 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1290 MIPSRH_Imm(False
, no_bits
)));
1291 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1293 MIPSRH_Imm(False
, no_bits
)));
1294 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1296 MIPSRH_Imm(False
, no_bits
)));
1297 addInstr(env
, MIPSInstr_Mul(r_dst
, r_srcL
, r_srcR
));
1300 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
1301 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1307 if (e
->Iex
.Binop
.op
== Iop_CmpF64
) {
1308 HReg r_srcL
, r_srcR
;
1310 r_srcL
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
1311 r_srcR
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1313 r_srcL
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
1314 r_srcR
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1316 #if (__mips_isa_rev >= 6)
1317 HReg tmp
= newVRegI(env
);
1319 HReg result
= newVRegI(env
);
1320 if (mode64
) tmpf
= newVRegF(env
);
1321 else tmpf
= newVRegD(env
);
1322 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN
, tmpf
, r_srcL
, r_srcR
));
1323 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1324 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1325 MIPSRH_Imm(False
, 0x45)));
1326 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
,
1327 hregMIPS_GPR0(env
->mode64
),
1329 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT
, tmpf
, r_srcL
, r_srcR
));
1330 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1331 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1332 MIPSRH_Imm(False
, 0x1)));
1333 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1335 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ
, tmpf
, r_srcL
, r_srcR
));
1336 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1337 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1338 MIPSRH_Imm(False
, 0x40)));
1339 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1343 HReg tmp
= newVRegI(env
);
1344 HReg r_ccMIPS
= newVRegI(env
);
1345 HReg r_ccIR
= newVRegI(env
);
1346 HReg r_ccIR_b0
= newVRegI(env
);
1347 HReg r_ccIR_b2
= newVRegI(env
);
1348 HReg r_ccIR_b6
= newVRegI(env
);
1350 /* Create in dst, the IRCmpF64Result encoded result. */
1352 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ
, tmp
, r_srcL
, r_srcR
));
1353 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccMIPS
, tmp
,
1354 MIPSRH_Imm(False
, 1)));
1356 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN
, tmp
, r_srcL
, r_srcR
));
1357 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1360 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT
, tmp
, r_srcL
, r_srcR
));
1361 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
,
1362 tmp
, MIPSRH_Imm(False
, 2)));
1363 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1366 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_NGT
,
1367 tmp
, r_srcL
, r_srcR
));
1368 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, tmp
,
1369 MIPSRH_Imm(False
, 3)));
1371 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tmp
, tmp
, MIPSRH_Reg(tmp
)));
1372 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1373 MIPSRH_Imm(False
, 8)));
1374 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1376 /* Map compare result from MIPS to IR,
1377 conforming to CmpF64 definition.
1378 FP cmp result | MIPS | IR
1379 --------------------------
1386 /* r_ccIR_b0 = r_ccMIPS[0] | r_ccMIPS[3] */
1387 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
, r_ccIR_b0
, r_ccMIPS
,
1388 MIPSRH_Imm(False
, 0x3)));
1389 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR_b0
, r_ccMIPS
,
1390 MIPSRH_Reg(r_ccIR_b0
)));
1391 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b0
, r_ccIR_b0
,
1392 MIPSRH_Imm(False
, 0x1)));
1394 /* r_ccIR_b2 = r_ccMIPS[0] */
1395 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccIR_b2
, r_ccMIPS
,
1396 MIPSRH_Imm(False
, 0x2)));
1397 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b2
, r_ccIR_b2
,
1398 MIPSRH_Imm(False
, 0x4)));
1400 /* r_ccIR_b6 = r_ccMIPS[0] | r_ccMIPS[1] */
1401 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
, r_ccIR_b6
,
1402 r_ccMIPS
, MIPSRH_Imm(False
, 0x1)));
1403 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR_b6
, r_ccMIPS
,
1404 MIPSRH_Reg(r_ccIR_b6
)));
1405 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccIR_b6
, r_ccIR_b6
,
1406 MIPSRH_Imm(False
, 0x6)));
1407 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b6
, r_ccIR_b6
,
1408 MIPSRH_Imm(False
, 0x40)));
1410 /* r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 */
1411 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR
, r_ccIR_b0
,
1412 MIPSRH_Reg(r_ccIR_b2
)));
1413 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR
, r_ccIR
,
1414 MIPSRH_Reg(r_ccIR_b6
)));
1419 if (e
->Iex
.Binop
.op
== Iop_CmpF32
) {
1420 #if (__mips_isa_rev >= 6)
1421 HReg r_srcL
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
1422 HReg r_srcR
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1423 HReg tmp
= newVRegI(env
);
1425 HReg result
= newVRegI(env
);
1426 if (mode64
) tmpf
= newVRegF(env
);
1427 else tmpf
= newVRegD(env
);
1428 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN_S
, tmpf
, r_srcL
, r_srcR
));
1429 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1430 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1431 MIPSRH_Imm(False
, 0x45)));
1432 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
,
1433 hregMIPS_GPR0(env
->mode64
),
1435 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT_S
, tmpf
, r_srcL
, r_srcR
));
1436 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1437 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1438 MIPSRH_Imm(False
, 0x1)));
1439 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1441 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ_S
, tmpf
, r_srcL
, r_srcR
));
1442 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1443 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1444 MIPSRH_Imm(False
, 0x40)));
1445 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1451 if (e
->Iex
.Binop
.op
== Iop_DivModU32to32
||
1452 e
->Iex
.Binop
.op
== Iop_DivModS32to32
) {
1453 HReg tLo
= newVRegI(env
);
1454 HReg tHi
= newVRegI(env
);
1455 HReg mask
= newVRegI(env
);
1456 HReg tLo_1
= newVRegI(env
);
1457 HReg tHi_1
= newVRegI(env
);
1458 HReg r_dst
= newVRegI(env
);
1459 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS32to32
);
1461 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1462 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1463 #if (__mips_isa_rev >= 6)
1464 addInstr(env
, MIPSInstr_Divr6(syned
/* Unsigned or Signed */ ,
1465 True
/* 32bit or 64bit div */ ,
1467 tLo
, r_srcL
, r_srcR
));
1468 addInstr(env
, MIPSInstr_Divr6(syned
/* Unsigned or Signed */ ,
1469 True
/*3 2bit or 64bit div */ ,
1471 tHi
, r_srcL
, r_srcR
));
1473 addInstr(env
, MIPSInstr_Div(syned
, True
, r_srcL
, r_srcR
));
1474 addInstr(env
, MIPSInstr_Mfhi(tHi
));
1475 addInstr(env
, MIPSInstr_Mflo(tLo
));
1477 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tHi_1
, tHi
,
1478 MIPSRH_Imm(False
, 32)));
1480 addInstr(env
, MIPSInstr_LI(mask
, 0xffffffff));
1481 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1484 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1485 MIPSRH_Reg(tLo_1
)));
1490 if (e
->Iex
.Binop
.op
== Iop_DivS32
||
1491 e
->Iex
.Binop
.op
== Iop_DivU32
||
1492 (e
->Iex
.Binop
.op
== Iop_DivS64
&& mode64
) ||
1493 (e
->Iex
.Binop
.op
== Iop_DivU64
&& mode64
)) {
1494 HReg r_dst
= newVRegI(env
);
1495 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivS32
||
1496 e
->Iex
.Binop
.op
== Iop_DivS64
);
1497 Bool div32
= toBool(e
->Iex
.Binop
.op
== Iop_DivS32
||
1498 e
->Iex
.Binop
.op
== Iop_DivU32
);
1499 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1500 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1501 #if (__mips_isa_rev >= 6)
1502 addInstr(env
, MIPSInstr_Divr6(syned
, div32
, False
,
1503 r_dst
, r_srcL
, r_srcR
));
1505 addInstr(env
, MIPSInstr_Div(syned
, div32
, r_srcL
, r_srcR
));
1506 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1511 if (e
->Iex
.Binop
.op
== Iop_8HLto16
1512 || e
->Iex
.Binop
.op
== Iop_16HLto32
) {
1513 HReg tHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1514 HReg tLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1515 HReg tLo_1
= newVRegI(env
);
1516 HReg tHi_1
= newVRegI(env
);
1517 HReg r_dst
= newVRegI(env
);
1520 switch (e
->Iex
.Binop
.op
) {
1533 /* sll tHi_1, tHi, shift
1534 and tLo_1, tLo, mask
1535 or r_dst, tHi_1, tLo_1 */
1536 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tHi_1
, tHi
,
1537 MIPSRH_Imm(False
, shift
)));
1538 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1539 MIPSRH_Imm(False
, mask
)));
1540 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1541 MIPSRH_Reg(tLo_1
)));
1545 if (e
->Iex
.Binop
.op
== Iop_32HLto64
) {
1547 HReg tHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1548 HReg tLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1549 HReg tLo_1
= newVRegI(env
);
1550 HReg tHi_1
= newVRegI(env
);
1551 HReg r_dst
= newVRegI(env
);
1552 HReg mask
= newVRegI(env
);
1554 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tHi_1
, tHi
,
1555 MIPSRH_Imm(False
, 32)));
1557 addInstr(env
, MIPSInstr_LI(mask
, 0xffffffff));
1558 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1560 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1561 MIPSRH_Reg(tLo_1
)));
1566 if (e
->Iex
.Binop
.op
== Iop_F32toI64S
) {
1568 HReg valS
= newVRegI(env
);
1569 HReg tmpF
= newVRegF(env
);
1570 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1572 /* CVTLS tmpF, valF */
1573 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1574 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpF
, valF
));
1575 set_MIPS_rounding_default(env
);
1577 /* Doubleword Move from Floating Point
1579 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, valS
, tmpF
));
1584 if (e
->Iex
.Binop
.op
== Iop_F64toI64S
) {
1586 HReg valS
= newVRegI(env
);
1587 HReg tmpF
= newVRegF(env
);
1588 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1590 /* CVTLS tmpF, valF */
1591 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1592 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, tmpF
, valF
));
1593 set_MIPS_rounding_default(env
);
1595 /* Doubleword Move from Floating Point
1597 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, valS
, tmpF
));
1602 if (e
->Iex
.Binop
.op
== Iop_F64toI32S
) {
1605 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1607 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1608 HReg valS
= newVRegF(env
);
1609 HReg r_dst
= newVRegI(env
);
1611 /* CVTWD valS, valD */
1612 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1613 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWD
, valS
, valD
));
1614 set_MIPS_rounding_default(env
);
1616 /* Move Word From Floating Point
1618 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1623 if (e
->Iex
.Binop
.op
== Iop_F32toI32U
) {
1624 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1625 HReg tmpD
= newVRegD(env
);
1626 HReg r_dst
= newVRegI(env
);
1629 /* CVTLS tmpD, valF */
1630 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1631 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpD
, valF
));
1632 set_MIPS_rounding_default(env
);
1634 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
1635 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
1638 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
1641 #if defined (_MIPSEL)
1642 addInstr(env
, MIPSInstr_Load(4, r_dst
, am_addr
, mode64
));
1643 #elif defined (_MIPSEB)
1644 addInstr(env
, MIPSInstr_Load(4, r_dst
, nextMIPSAModeFloat(am_addr
),
1654 if (e
->Iex
.Binop
.op
== Iop_F64toI64U
) {
1656 HReg tmp
= newVRegV(env
);
1658 r_src
= iselFltExpr( env
, e
->Iex
.Binop
.arg2
);
1659 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
1660 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_U
, MSA_F_DW
, tmp
, r_src
));
1661 HReg r_dst
= newVRegI(env
);
1663 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dst
, MSA_DFN_D
| 0));
1664 set_MIPS_rounding_default_MSA(env
);
1668 if (e
->Iex
.Binop
.op
== Iop_GetElem8x16
) {
1669 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1670 HReg r_dst
= newVRegI(env
);
1671 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1676 MIPSInstr_MsaElm(MSA_COPY_U
, v_src
, r_dst
,
1678 (tmp
->Mrh
.Imm
.imm16
& 0x0f)));
1682 HReg v_tmp
= newVRegV(env
);
1684 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_B
, v_tmp
, v_src
,
1687 MIPSInstr_MsaElm(MSA_COPY_U
, v_tmp
, r_dst
,
1697 if (e
->Iex
.Binop
.op
== Iop_GetElem16x8
) {
1698 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1699 HReg r_dst
= newVRegI(env
);
1700 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1705 MIPSInstr_MsaElm(MSA_COPY_U
, v_src
, r_dst
,
1707 (tmp
->Mrh
.Imm
.imm16
& 0x07)));
1711 HReg v_tmp
= newVRegV(env
);
1713 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_H
, v_tmp
, v_src
,
1716 MIPSInstr_MsaElm(MSA_COPY_U
, v_tmp
, r_dst
,
1725 if (e
->Iex
.Binop
.op
== Iop_GetElem32x4
) {
1726 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1727 HReg r_dst
= newVRegI(env
);
1728 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1732 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dst
,
1734 (tmp
->Mrh
.Imm
.imm16
& 0x03)));
1738 HReg v_tmp
= newVRegV(env
);
1740 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_W
, v_tmp
, v_src
,
1743 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dst
,
1751 if (e
->Iex
.Binop
.op
== Iop_GetElem64x2
) {
1753 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1754 HReg r_dst
= newVRegI(env
);
1755 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1760 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dst
,
1762 (tmp
->Mrh
.Imm
.imm16
& 0x01)));
1766 HReg v_tmp
= newVRegV(env
);
1768 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_D
, v_tmp
, v_src
,
1771 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dst
,
1780 if (e
->Iex
.Binop
.op
== Iop_F32toI32S
) {
1781 HReg valS
= newVRegF(env
);
1782 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1783 HReg r_dst
= newVRegI(env
);
1785 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1786 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWS
, valS
, valF
));
1787 set_MIPS_rounding_default(env
);
1789 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1794 /* -------- DSP ASE -------- */
1795 /* All used cases involving host-side helper calls. */
1797 switch (e
->Iex
.Binop
.op
) {
1799 fn
= &h_generic_calc_HAdd8Ux4
; break;
1801 fn
= &h_generic_calc_HSub8Ux4
; break;
1803 fn
= &h_generic_calc_HSub16Sx2
; break;
1805 fn
= &h_generic_calc_QSub8Ux4
; break;
1810 /* What's the retloc? */
1811 RetLoc rloc
= mk_RetLoc_INVALID();
1812 if (ty
== Ity_I32
) {
1813 rloc
= mk_RetLoc_simple(RLPri_Int
);
1815 else if (ty
== Ity_I64
) {
1816 rloc
= mode64
? mk_RetLoc_simple(RLPri_Int
) :
1817 mk_RetLoc_simple(RLPri_2Int
);
1824 HReg regL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1825 HReg regR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1826 HReg res
= newVRegI(env
);
1827 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR4(env
->mode64
), regL
));
1828 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR5(env
->mode64
), regR
));
1829 argiregs
|= (1 << 4);
1830 argiregs
|= (1 << 5);
1831 addInstr(env
, MIPSInstr_CallAlways( MIPScc_AL
,
1834 addInstr(env
, mk_iMOVds_RR(res
, hregMIPS_GPR2(env
->mode64
)));
1840 /* --------- UNARY OP --------- */
1842 IROp op_unop
= e
->Iex
.Unop
.op
;
1854 HReg r_dst
= newVRegI(env
);
1855 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1899 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, sz32
, r_dst
, r_src
,
1900 MIPSRH_Imm(False
, amt
)));
1901 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, sz32
, r_dst
, r_dst
,
1902 MIPSRH_Imm(False
, amt
)));
1906 /* not(x) = nor(x,x) */
1908 HReg r_dst
= newVRegI(env
);
1909 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1910 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
1912 addInstr(env
, MIPSInstr_LI(r_dst
, 0x1));
1913 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, r_dst
, r_srcR
));
1921 HReg r_dst
= newVRegI(env
);
1922 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1923 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
1925 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dst
, r_srcL
, r_srcR
));
1929 case Iop_ReinterpF32asI32
: {
1930 HReg fr_src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
1931 HReg r_dst
= newVRegI(env
);
1933 /* Move Word From Floating Point
1934 mfc1 r_dst, fr_src */
1935 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, fr_src
));
1940 case Iop_ReinterpF64asI64
: {
1942 HReg fr_src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
1943 HReg r_dst
= newVRegI(env
);
1945 /* Doubleword Move from Floating Point
1946 mfc1 r_dst, fr_src */
1947 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, r_dst
, fr_src
));
1952 case Iop_F64toI32S
: {
1955 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1957 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1958 HReg valS
= newVRegF(env
);
1959 HReg r_dst
= newVRegI(env
);
1961 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1962 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWD
, valS
, valD
));
1963 set_MIPS_rounding_default(env
);
1965 /* Move Word From Floating Point
1967 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1976 return iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1978 case Iop_32HIto16
: {
1979 HReg r_dst
= newVRegI(env
);
1980 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1981 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
1982 r_dst
, r_src
, MIPSRH_Imm(False
, 16)));
1989 UShort mask
= (op_unop
== Iop_64to1
) ? 0x1 : 0xFF;
1990 r_dst
= newVRegI(env
);
1992 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1995 iselInt64Expr(&tmp
, &r_src
, env
, e
->Iex
.Unop
.arg
);
1997 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_dst
, r_src
,
1998 MIPSRH_Imm(False
, mask
)));
2003 HReg r_dst
= newVRegI(env
);
2004 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2005 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
2006 r_dst
, r_src
, MIPSRH_Imm(False
, 8)));
2018 HReg r_dst
= newVRegI(env
);
2019 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2027 mask
= toUShort(0x1);
2034 mask
= toUShort(0xFF);
2040 mask
= toUShort(0xFFFF);
2046 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_dst
, r_src
,
2047 MIPSRH_Imm(False
, mask
)));
2052 HReg r_dst
= newVRegI(env
);
2053 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2055 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
/*!32bit shift */,
2056 r_dst
, r_src
, MIPSRH_Imm(False
, 32)));
2057 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, False
/*!32bit shift */,
2058 r_dst
, r_dst
, MIPSRH_Imm(False
, 32)));
2062 case Iop_64HIto32
: {
2064 HReg r_dst
= newVRegI(env
);
2065 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2066 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
/*64bit shift */,
2067 r_dst
, r_src
, MIPSRH_Imm(True
, 32)));
2071 iselInt64Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2078 HReg r_dst
= newVRegI(env
);
2079 r_dst
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2083 iselInt64Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2089 vassert(env
->mode64
);
2090 HReg r_dst
= newVRegI(env
);
2091 r_dst
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2096 HReg r_dst
= newVRegI(env
);
2097 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2099 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/*!32bit shift */,
2100 r_dst
, r_src
, MIPSRH_Imm(True
, 0)));
2105 case Iop_CmpNEZ16
: {
2106 HReg r_dst
= newVRegI(env
);
2107 HReg tmp
= newVRegI(env
);
2108 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2109 UShort mask
= (op_unop
== Iop_CmpNEZ8
) ? 0xFF : 0xFFFF;
2111 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, r_src
,
2112 MIPSRH_Imm(False
, mask
)));
2113 addInstr(env
, MIPSInstr_Cmp(False
, True
, r_dst
, tmp
,
2114 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2118 case Iop_CmpNEZ32
: {
2119 HReg r_dst
= newVRegI(env
);
2120 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2122 addInstr(env
, MIPSInstr_Cmp(False
, True
, r_dst
, r_src
,
2123 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2127 case Iop_CmpwNEZ32
: {
2128 HReg r_dst
= newVRegI(env
);
2129 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2131 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, hregMIPS_GPR0(mode64
),
2132 MIPSRH_Reg(r_src
)));
2134 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2135 MIPSRH_Reg(r_src
)));
2136 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, r_dst
, r_dst
,
2137 MIPSRH_Imm(False
, 31)));
2145 if (op_unop
== Iop_Left64
&& !mode64
)
2147 HReg r_dst
= newVRegI(env
);
2148 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2149 MIPSAluOp op
= (op_unop
== Iop_Left64
) ? Malu_DSUB
: Malu_SUB
;
2150 addInstr(env
, MIPSInstr_Alu(op
, r_dst
,
2151 hregMIPS_GPR0(mode64
),
2152 MIPSRH_Reg(r_src
)));
2153 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2154 MIPSRH_Reg(r_src
)));
2162 HReg r_dst
= newVRegI(env
);
2163 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2164 MIPSUnaryOp op
= (op_unop
== Iop_Clz64
) ? Mun_DCLZ
: Mun_CLZ
;
2165 addInstr(env
, MIPSInstr_Unary(op
, r_dst
, r_src
));
2169 case Iop_CmpNEZ64
: {
2171 HReg r_dst
= newVRegI(env
);
2174 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2176 r_src
= newVRegI(env
);
2177 iselInt64Expr(&hi
, &lo
, env
, e
->Iex
.Unop
.arg
);
2178 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_src
, lo
, MIPSRH_Reg(hi
)));
2180 addInstr(env
, MIPSInstr_Cmp(False
, !(env
->mode64
), r_dst
, r_src
,
2181 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2185 case Iop_CmpwNEZ64
: {
2187 HReg tmp2
= newVRegI(env
);
2188 vassert(env
->mode64
);
2189 tmp1
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2191 addInstr(env
, MIPSInstr_Alu(Malu_DSUB
, tmp2
, hregMIPS_GPR0(mode64
),
2194 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp2
, tmp2
, MIPSRH_Reg(tmp1
)));
2195 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
, tmp2
, tmp2
,
2196 MIPSRH_Imm (False
, 63)));
2200 case Iop_128HIto64
: {
2203 iselInt128Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2204 return rHi
; /* and abandon rLo .. poor wee thing :-) */
2210 iselInt128Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2211 return rLo
; /* and abandon rLo .. poor wee thing :-) */
2214 case Iop_V128to32
: {
2215 HReg i_dst
= newVRegI(env
);
2216 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2219 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, i_dst
, MSA_DFN_W
));
2223 case Iop_V128HIto64
: {
2226 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2227 HReg reg
= newVRegI(env
);
2229 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 1));
2233 case Iop_V128to64
: {
2236 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2237 HReg reg
= newVRegI(env
);
2239 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 0));
2243 case Iop_F32toF16x4_DEP
: {
2246 HReg v_arg
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2247 HReg v_src
= newVRegV(env
);
2248 set_guest_MIPS_rounding_mode_MSA(env
);
2250 MIPSInstr_Msa3RF(MSA_FEXDO
, MSA_F_WH
,
2251 v_src
, v_arg
, v_arg
));
2252 set_MIPS_rounding_default_MSA(env
);
2253 HReg reg
= newVRegI(env
);
2255 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 0));
2264 /* -------- DSP ASE -------- */
2265 /* All Unop cases involving host-side helper calls. */
2267 switch (e
->Iex
.Unop
.op
) {
2268 case Iop_CmpNEZ16x2
:
2269 fn
= &h_generic_calc_CmpNEZ16x2
; break;
2271 fn
= &h_generic_calc_CmpNEZ8x4
; break;
2276 RetLoc rloc
= mk_RetLoc_INVALID();
2277 if (ty
== Ity_I32
) {
2278 rloc
= mk_RetLoc_simple(RLPri_Int
);
2280 else if (ty
== Ity_I64
) {
2281 rloc
= mode64
? mk_RetLoc_simple(RLPri_Int
) :
2282 mk_RetLoc_simple(RLPri_2Int
);
2289 HReg regL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2290 HReg res
= newVRegI(env
);
2291 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR4(env
->mode64
), regL
));
2292 argiregs
|= (1 << 4);
2293 addInstr(env
, MIPSInstr_CallAlways( MIPScc_AL
,
2296 addInstr(env
, mk_iMOVds_RR(res
, hregMIPS_GPR2(env
->mode64
)));
2303 /* --------- GET --------- */
2305 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
2306 || ((ty
== Ity_I64
) && mode64
)) {
2307 HReg r_dst
= newVRegI(env
);
2309 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
2310 GuestStatePointer(mode64
));
2311 addInstr(env
, MIPSInstr_Load(toUChar(sizeofIRType(ty
)), r_dst
, am_addr
,
2318 /* --------- ITE --------- */
2320 if ((ty
== Ity_I8
|| ty
== Ity_I16
||
2321 ty
== Ity_I32
|| ((ty
== Ity_I64
))) &&
2322 typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
) {
2323 HReg r0
= iselWordExpr_R(env
, e
->Iex
.ITE
.iffalse
);
2324 HReg r1
= iselWordExpr_R(env
, e
->Iex
.ITE
.iftrue
);
2325 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
2326 HReg r_dst
= newVRegI(env
);
2329 * movn r_dst, r1, r_cond
2331 #if (__mips_isa_rev >= 6)
2332 HReg r_temp
= newVRegI(env
);
2333 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dst
, r0
, r_cond
));
2334 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, r1
, r_cond
));
2335 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2336 MIPSRH_Reg(r_temp
)));
2339 addInstr(env
, mk_iMOVds_RR(r_dst
, r0
));
2340 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dst
, r1
, r_cond
));
2347 /* --------- LITERAL --------- */
2348 /* 32/16/8-bit literals */
2351 HReg r_dst
= newVRegI(env
);
2352 IRConst
*con
= e
->Iex
.Const
.con
;
2357 l
= (Long
) con
->Ico
.U64
;
2360 l
= (Long
) (Int
) con
->Ico
.U32
;
2363 l
= (Long
) (Int
) (Short
) con
->Ico
.U16
;
2366 l
= (Long
) (Int
) (Char
) con
->Ico
.U8
;
2369 l
= con
->Ico
.U1
? 1 : 0;
2372 vpanic("iselIntExpr_R.const(mips)");
2374 addInstr(env
, MIPSInstr_LI(r_dst
, (ULong
) l
));
2378 /* --------- CCALL --------- */
2380 HReg r_dst
= newVRegI(env
);
2381 vassert(ty
== e
->Iex
.CCall
.retty
);
2383 /* be very restrictive for now. Only 32/64-bit ints allowed for
2384 args, and 64 and 32 bits for return type. Don't forget to change
2385 the RetLoc if more return types are allowed in future. */
2386 if (e
->Iex
.CCall
.retty
!= Ity_I64
&& e
->Iex
.CCall
.retty
!= Ity_I32
)
2389 /* Marshal args, do the call, clear stack. */
2391 RetLoc rloc
= mk_RetLoc_INVALID();
2392 doHelperCall(&addToSp
, &rloc
, env
, NULL
/*guard*/, e
->Iex
.CCall
.cee
,
2393 e
->Iex
.CCall
.retty
, e
->Iex
.CCall
.args
);
2395 vassert(is_sane_RetLoc(rloc
));
2396 vassert(rloc
.pri
== RLPri_Int
);
2397 vassert(addToSp
== 0);
2398 addInstr(env
, mk_iMOVds_RR(r_dst
, hregMIPS_GPR2(mode64
)));
2402 #if (__mips_isa_rev >= 6)
2404 HReg dst
= newVRegI(env
);
2405 HReg src1
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg1
);
2406 HReg src2
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg2
);
2407 HReg src3
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg3
);
2408 HReg src4
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg4
);
2409 switch (e
->Iex
.Qop
.details
->op
) {
2411 addInstr(env
, MIPSInstr_Bitswap(Rotx32
, dst
, src1
, src2
, src3
, src4
));
2414 addInstr(env
, MIPSInstr_Bitswap(Rotx64
, dst
, src1
, src2
, src3
, src4
));
2425 } /* end switch(e->tag) */
2427 /* We get here if no pattern matched. */
2429 vex_printf("--------------->\n");
2430 if (e
->tag
== Iex_RdTmp
)
2431 vex_printf("Iex_RdTmp \n");
2434 vpanic("iselWordExpr_R(mips): cannot reduce tree");
2437 /* --------------------- RH --------------------- */
2439 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2440 (reg-or-halfword-immediate). It's important to specify whether the
2441 immediate is to be regarded as signed or not. If yes, this will
2442 never return -32768 as an immediate; this guaranteed that all
2443 signed immediates that are return can have their sign inverted if
2446 static MIPSRH
*iselWordExpr_RH(ISelEnv
* env
, Bool syned
, IRExpr
* e
)
2448 MIPSRH
*ri
= iselWordExpr_RH_wrk(env
, syned
, e
);
2449 /* sanity checks ... */
2452 vassert(ri
->Mrh
.Imm
.syned
== syned
);
2454 vassert(ri
->Mrh
.Imm
.imm16
!= 0x8000);
2457 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2458 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2461 vpanic("iselIntExpr_RH: unknown mips RH tag");
2465 /* DO NOT CALL THIS DIRECTLY ! */
2466 static MIPSRH
*iselWordExpr_RH_wrk(ISelEnv
* env
, Bool syned
, IRExpr
* e
)
2470 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2471 vassert(ty
== Ity_I1
|| ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
||
2472 ((ty
== Ity_I64
) && env
->mode64
));
2474 /* special case: immediate */
2475 if (e
->tag
== Iex_Const
) {
2476 IRConst
*con
= e
->Iex
.Const
.con
;
2477 /* What value are we aiming to generate? */
2479 /* Note: Not sign-extending - we carry 'syned' around */
2481 vassert(env
->mode64
);
2485 u
= 0xFFFFFFFF & con
->Ico
.U32
;
2488 u
= 0x0000FFFF & con
->Ico
.U16
;
2491 u
= 0x000000FF & con
->Ico
.U8
;
2494 u
= 0x00000001 & con
->Ico
.U1
;
2497 vpanic("iselIntExpr_RH.Iex_Const(mips)");
2500 /* Now figure out if it's representable. */
2501 if (!syned
&& u
<= 65535) {
2502 return MIPSRH_Imm(False
/*unsigned */ , toUShort(u
& 0xFFFF));
2504 if (syned
&& l
>= -32767 && l
<= 32767) {
2505 return MIPSRH_Imm(True
/*signed */ , toUShort(u
& 0xFFFF));
2507 /* no luck; use the Slow Way. */
2509 /* default case: calculate into a register and return that */
2510 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2513 /* --------------------- RH5u --------------------- */
2515 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2516 being an immediate in the range 1 .. 31 inclusive. Used for doing
2519 static MIPSRH
*iselWordExpr_RH5u(ISelEnv
* env
, IRExpr
* e
)
2522 ri
= iselWordExpr_RH5u_wrk(env
, e
);
2523 /* sanity checks ... */
2526 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 31);
2527 vassert(!ri
->Mrh
.Imm
.syned
);
2530 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcInt32
);
2531 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2534 vpanic("iselIntExpr_RH5u: unknown mips RH tag");
2538 /* DO NOT CALL THIS DIRECTLY ! */
2539 static MIPSRH
*iselWordExpr_RH5u_wrk(ISelEnv
* env
, IRExpr
* e
)
2541 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2542 vassert(ty
== Ity_I8
);
2544 /* special case: immediate */
2545 if (e
->tag
== Iex_Const
2546 && e
->Iex
.Const
.con
->tag
== Ico_U8
2547 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 31) {
2548 return MIPSRH_Imm(False
/*unsigned */ , e
->Iex
.Const
.con
->Ico
.U8
);
2551 /* default case: calculate into a register and return that */
2552 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2555 /* --------------------- RH6u --------------------- */
2557 static MIPSRH
*iselWordExpr_RH6u ( ISelEnv
* env
, IRExpr
* e
)
2560 ri
= iselWordExpr_RH6u_wrk(env
, e
);
2561 /* sanity checks ... */
2564 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 63);
2565 vassert(!ri
->Mrh
.Imm
.syned
);
2568 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2569 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2572 vpanic("iselIntExpr_RH6u: unknown RI tag");
2576 /* DO NOT CALL THIS DIRECTLY ! */
2577 static MIPSRH
*iselWordExpr_RH6u_wrk ( ISelEnv
* env
, IRExpr
* e
)
2579 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2580 vassert(ty
== Ity_I8
);
2582 /* special case: immediate */
2583 if (e
->tag
== Iex_Const
2584 && e
->Iex
.Const
.con
->tag
== Ico_U8
2585 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 63)
2587 return MIPSRH_Imm(False
/*unsigned */ ,
2588 e
->Iex
.Const
.con
->Ico
.U8
);
2591 /* default case: calculate into a register and return that */
2592 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2594 /* --------------------- RH7u --------------------- */
2596 static MIPSRH
*iselWordExpr_RH7u ( ISelEnv
* env
, IRExpr
* e
)
2599 ri
= iselWordExpr_RH7u_wrk(env
, e
);
2600 /* sanity checks ... */
2603 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 127);
2604 vassert(!ri
->Mrh
.Imm
.syned
);
2607 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2608 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2611 vpanic("iselIntExpr_RH7u: unknown RI tag");
2615 /* DO NOT CALL THIS DIRECTLY ! */
2616 static MIPSRH
*iselWordExpr_RH7u_wrk ( ISelEnv
* env
, IRExpr
* e
)
2618 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2619 vassert(ty
== Ity_I8
);
2621 /* special case: immediate */
2622 if (e
->tag
== Iex_Const
2623 && e
->Iex
.Const
.con
->tag
== Ico_U8
2624 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 127)
2626 return MIPSRH_Imm(False
/*unsigned */ ,
2627 e
->Iex
.Const
.con
->Ico
.U8
);
2630 /* default case: calculate into a register and return that */
2631 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2635 /* --------------------- CONDCODE --------------------- */
2637 /* Generate code to evaluated a bit-typed expression, returning the
2638 condition code which would correspond when the expression would
2639 notionally have returned 1. */
2641 static MIPSCondCode
iselCondCode(ISelEnv
* env
, IRExpr
* e
)
2643 MIPSCondCode cc
= iselCondCode_wrk(env
,e
);
2644 vassert(cc
!= MIPScc_NV
);
2648 /* DO NOT CALL THIS DIRECTLY ! */
2649 static MIPSCondCode
iselCondCode_wrk(ISelEnv
* env
, IRExpr
* e
)
2652 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I1
);
2653 /* Cmp*32*(x,y) ? */
2654 if (e
->tag
== Iex_Binop
2655 && (e
->Iex
.Binop
.op
== Iop_CmpEQ32
2656 || e
->Iex
.Binop
.op
== Iop_CmpNE32
2657 || e
->Iex
.Binop
.op
== Iop_CmpNE64
2658 || e
->Iex
.Binop
.op
== Iop_CmpLT32S
2659 || e
->Iex
.Binop
.op
== Iop_CmpLT32U
2660 || e
->Iex
.Binop
.op
== Iop_CmpLT64U
2661 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
2662 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
2663 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
2664 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
2665 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ32
2666 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
)) {
2668 Bool syned
= (e
->Iex
.Binop
.op
== Iop_CmpLT32S
2669 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
2670 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
2671 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
);
2673 HReg dst
= newVRegI(env
);
2674 HReg r1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
2675 HReg r2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
2679 switch (e
->Iex
.Binop
.op
) {
2681 case Iop_CasCmpEQ32
:
2718 case Iop_CasCmpEQ64
:
2723 vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
2727 addInstr(env
, MIPSInstr_Cmp(syned
, size32
, dst
, r1
, r2
, cc
));
2728 /* Store result to guest_COND */
2729 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2731 addInstr(env
, MIPSInstr_Store(4,
2732 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2733 am_addr
->Mam
.IR
.base
),
2737 if (e
->tag
== Iex_Unop
&& e
->Iex
.Binop
.op
== Iop_Not1
) {
2738 HReg r_dst
= newVRegI(env
);
2739 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2740 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
2742 addInstr(env
, MIPSInstr_LI(r_dst
, 0x1));
2743 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, r_dst
, r_srcR
));
2744 /* Store result to guest_COND */
2745 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2747 addInstr(env
, MIPSInstr_Store(4,
2748 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2749 am_addr
->Mam
.IR
.base
),
2754 if (e
->tag
== Iex_Unop
2755 && (e
->Iex
.Unop
.op
== Iop_CmpNEZ32
2756 || ((e
->Iex
.Unop
.op
== Iop_CmpNEZ64
) && mode64
))) {
2757 HReg r_dst
= newVRegI(env
);
2758 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2760 addInstr(env
, MIPSInstr_Cmp(False
, !mode64
, r_dst
, r_src
,
2761 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2762 /* Store result to guest_COND */
2763 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2765 addInstr(env
, MIPSInstr_Store(4,
2766 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2767 am_addr
->Mam
.IR
.base
),
2772 if (e
->tag
== Iex_Binop
2773 && (e
->Iex
.Binop
.op
== Iop_And1
|| e
->Iex
.Binop
.op
== Iop_Or1
)) {
2774 HReg r_argL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
2775 HReg r_argR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
2776 HReg r_dst
= newVRegI(env
);
2777 addInstr(env
, MIPSInstr_Alu(e
->Iex
.Binop
.op
== Iop_And1
? Malu_AND
: Malu_OR
,
2778 r_dst
, r_argL
, MIPSRH_Reg(r_argR
)));
2779 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_dst
, r_dst
, MIPSRH_Imm(False
, 1)));
2780 /* Store result to guest_COND */
2781 /* sewardj 2019Dec13: this seems wrong to me. The host-side instruction
2782 selector shouldn't touch the guest-side state, except in response to
2783 Iex_Get and Ist_Put. */
2784 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2786 addInstr(env
, MIPSInstr_Store(4,
2787 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2788 am_addr
->Mam
.IR
.base
),
2793 if (e
->tag
== Iex_RdTmp
) {
2794 HReg r_dst
= iselWordExpr_R_wrk(env
, e
);
2795 /* Store result to guest_COND */
2796 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2798 addInstr(env
, MIPSInstr_Store(4,
2799 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2800 am_addr
->Mam
.IR
.base
),
2805 vex_printf("iselCondCode(mips): No such tag(%u)\n", e
->tag
);
2807 vpanic("iselCondCode(mips)");
2810 /*---------------------------------------------------------*/
2811 /*--- ISEL: Vector expressions (128 bit - SIMD) ---*/
2812 /*---------------------------------------------------------*/
2814 /* Compute a vector value into vector register. */
2815 static HReg
iselV128Expr (ISelEnv
* env
, IRExpr
* e
) {
2817 HReg r
= iselV128Expr_wrk(env
, e
);
2818 vassert(hregClass(r
) == HRcVec128
);
2819 vassert(hregIsVirtual(r
));
2823 /* DO NOT CALL THIS DIRECTLY ! */
2824 static HReg
iselV128Expr_wrk(ISelEnv
* env
, IRExpr
* e
) {
2825 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2827 vassert(ty
== Ity_V128
);
2829 if (e
->tag
== Iex_RdTmp
) {
2830 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
2833 if (e
->tag
== Iex_Load
) {
2834 vassert (e
->Iex
.Load
.ty
== Ity_V128
);
2835 HReg v_dst
= newVRegV(env
);
2836 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, 0, iselWordExpr_R(env
,
2837 e
->Iex
.Load
.addr
), v_dst
, MSA_B
));
2841 if (e
->tag
== Iex_Get
) {
2842 HReg v_dst
= newVRegV(env
);
2843 #if defined(_MIPSEB)
2844 HReg r_addr
= newVRegI(env
);
2845 vassert(!(e
->Iex
.Get
.offset
& ~0x7FFF));
2846 addInstr(env
, MIPSInstr_Alu(mode64
? Malu_DADD
: Malu_ADD
, r_addr
, GuestStatePointer(mode64
),
2847 MIPSRH_Imm(True
, e
->Iex
.Get
.offset
)));
2848 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, 0, r_addr
, v_dst
, MSA_B
));
2850 vassert(!(e
->Iex
.Get
.offset
& 7));
2851 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, e
->Iex
.Get
.offset
>> 3,
2852 GuestStatePointer(mode64
), v_dst
, MSA_D
));
2857 if (e
->tag
== Iex_Unop
) {
2858 IROp op_unop
= e
->Iex
.Unop
.op
;
2862 HReg v_dst
= newVRegV(env
);
2863 HReg v_help
= newVRegV(env
);
2864 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2866 MIPSInstr_Msa3R(MSA_SUBV
, MSA_D
, v_help
, v_src
, v_src
));
2868 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_D
,
2869 v_dst
, v_src
, v_help
));
2874 HReg v_dst
= newVRegV(env
);
2875 HReg v_help
= newVRegV(env
);
2876 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2878 MIPSInstr_Msa3R(MSA_SUBV
, MSA_W
, v_help
, v_src
, v_src
));
2880 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_W
,
2881 v_dst
, v_src
, v_help
));
2886 HReg v_dst
= newVRegV(env
);
2887 HReg v_help
= newVRegV(env
);
2888 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2890 MIPSInstr_Msa3R(MSA_SUBV
, MSA_H
, v_help
, v_src
, v_src
));
2892 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_H
,
2893 v_dst
, v_src
, v_help
));
2898 HReg v_dst
= newVRegV(env
);
2899 HReg v_help
= newVRegV(env
);
2900 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2902 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
, v_help
, v_src
, v_src
));
2904 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_B
,
2905 v_dst
, v_src
, v_help
));
2910 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2911 HReg res
= newVRegV(env
);
2912 addInstr(env
, MIPSInstr_Msa2R(MSA_PCNT
, MSA_B
, v_src
, res
));
2917 HReg v_dst
= newVRegV(env
);
2918 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2919 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_src
, v_src
));
2923 case Iop_Reverse8sIn16_x8
: {
2924 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2925 HReg v_tmp
= newVRegV(env
);
2927 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2929 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2933 case Iop_Reverse8sIn32_x4
: {
2934 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2935 HReg v_tmp
= newVRegV(env
);
2937 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
, v_tmp
, v_src
, v_src
));
2939 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
, v_src
, v_tmp
, v_src
));
2941 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2943 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2947 case Iop_Reverse8sIn64_x2
: {
2948 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2949 HReg v_tmp
= newVRegV(env
);
2951 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_W
, v_tmp
, v_src
, v_src
));
2953 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_W
, v_src
, v_tmp
, v_src
));
2955 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
, v_tmp
, v_src
, v_src
));
2957 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
, v_src
, v_tmp
, v_src
));
2959 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2961 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2966 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2967 HReg v_dst
= newVRegV(env
);
2968 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_B
, v_src
, v_dst
));
2973 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2974 HReg v_dst
= newVRegV(env
);
2975 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_H
, v_src
, v_dst
));
2980 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2981 HReg v_dst
= newVRegV(env
);
2982 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_W
, v_src
, v_dst
));
2987 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2988 HReg v_dst
= newVRegV(env
);
2989 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_B
, v_src
, v_dst
));
2994 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2995 HReg v_dst
= newVRegV(env
);
2996 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_H
, v_src
, v_dst
));
3001 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3002 HReg v_dst
= newVRegV(env
);
3003 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_W
, v_src
, v_dst
));
3008 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3009 HReg v_dst
= newVRegV(env
);
3010 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_D
, v_src
, v_dst
));
3014 case Iop_Abs32Fx4
: {
3015 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3016 HReg v_dst
= newVRegV(env
);
3017 HReg v_help
= newVRegV(env
);
3019 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_WH
,
3020 v_help
, v_src
, v_src
));
3022 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_WH
, v_dst
, v_help
));
3026 case Iop_Abs64Fx2
: {
3027 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3028 HReg v_dst
= newVRegV(env
);
3029 HReg v_help
= newVRegV(env
);
3031 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_DW
,
3032 v_help
, v_src
, v_src
));
3034 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_DW
, v_dst
, v_help
));
3038 case Iop_RecipEst32Fx4
: {
3039 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3040 HReg v_dst
= newVRegV(env
);
3041 set_guest_MIPS_rounding_mode_MSA(env
);
3043 MIPSInstr_Msa2RF(MSA_FRCP
, MSA_F_WH
, v_dst
, v_src
));
3044 set_MIPS_rounding_default_MSA(env
);
3048 case Iop_RecipEst64Fx2
: {
3049 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3050 HReg v_dst
= newVRegV(env
);
3051 set_guest_MIPS_rounding_mode_MSA(env
);
3053 MIPSInstr_Msa2RF(MSA_FRCP
, MSA_F_DW
, v_dst
, v_src
));
3054 set_MIPS_rounding_default_MSA(env
);
3058 case Iop_RSqrtEst32Fx4
: {
3059 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3060 HReg v_dst
= newVRegV(env
);
3061 set_guest_MIPS_rounding_mode_MSA(env
);
3063 MIPSInstr_Msa2RF(MSA_FRSQRT
, MSA_F_WH
, v_dst
, v_src
));
3064 set_MIPS_rounding_default_MSA(env
);
3068 case Iop_RSqrtEst64Fx2
: {
3069 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3070 HReg v_dst
= newVRegV(env
);
3071 set_guest_MIPS_rounding_mode_MSA(env
);
3073 MIPSInstr_Msa2RF(MSA_FRSQRT
, MSA_F_DW
, v_dst
, v_src
));
3074 set_MIPS_rounding_default_MSA(env
);
3078 case Iop_F16toF32x4
: {
3079 HReg v_dst
= newVRegV(env
);
3083 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
3085 MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src
, v_dst
));
3087 MIPSInstr_MsaElm(MSA_INSERT
, r_src
, v_dst
,
3090 HReg r_srch
, r_srcl
;
3091 iselInt64Expr(&r_srch
, &r_srcl
, env
, e
->Iex
.Unop
.arg
);
3093 MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_srcl
, v_dst
));
3095 MIPSInstr_MsaElm(MSA_INSERT
, r_srch
, v_dst
,
3098 MIPSInstr_MsaElm(MSA_INSERT
, r_srcl
, v_dst
,
3101 MIPSInstr_MsaElm(MSA_INSERT
, r_srch
, v_dst
,
3106 MIPSInstr_Msa2RF(MSA_FEXUPR
, MSA_F_WH
, v_dst
, v_dst
));
3110 case Iop_I32UtoF32x4_DEP
: {
3111 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3112 HReg v_dst
= newVRegV(env
);
3113 set_guest_MIPS_rounding_mode_MSA(env
);
3115 MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_WH
, v_dst
, v_src
));
3116 set_MIPS_rounding_default_MSA(env
);
3120 case Iop_F32toI32Sx4_RZ
: {
3121 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3122 HReg v_dst
= newVRegV(env
);
3124 MIPSInstr_Msa2RF(MSA_FTRUNC_S
, MSA_F_WH
, v_dst
, v_src
));
3128 case Iop_F32toI32Ux4_RZ
: {
3129 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3130 HReg v_dst
= newVRegV(env
);
3132 MIPSInstr_Msa2RF(MSA_FTRUNC_U
, MSA_F_WH
, v_dst
, v_src
));
3136 case Iop_Log2_32Fx4
: {
3137 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3138 HReg v_dst
= newVRegV(env
);
3140 MIPSInstr_Msa2RF(MSA_FLOG2
, MSA_F_WH
, v_dst
, v_src
));
3144 case Iop_Log2_64Fx2
: {
3145 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3146 HReg v_dst
= newVRegV(env
);
3148 MIPSInstr_Msa2RF(MSA_FLOG2
, MSA_F_DW
, v_dst
, v_src
));
3151 case Iop_CmpNEZ8x16
: {
3152 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3153 HReg v_dst
= newVRegV(env
);
3154 HReg zero
= Zero(mode64
);
3155 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3157 MIPSInstr_Msa3R(MSA_CEQ
, MSA_B
, v_dst
, v_src
, v_dst
));
3158 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3161 case Iop_CmpNEZ16x8
: {
3162 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3163 HReg v_dst
= newVRegV(env
);
3164 HReg zero
= Zero(mode64
);
3165 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3167 MIPSInstr_Msa3R(MSA_CEQ
, MSA_H
, v_dst
, v_src
, v_dst
));
3168 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3171 case Iop_CmpNEZ32x4
: {
3172 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3173 HReg v_dst
= newVRegV(env
);
3174 HReg zero
= Zero(mode64
);
3175 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3177 MIPSInstr_Msa3R(MSA_CEQ
, MSA_W
, v_dst
, v_src
, v_dst
));
3178 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3181 case Iop_CmpNEZ64x2
: {
3182 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3183 HReg v_dst
= newVRegV(env
);
3184 HReg zero
= Zero(mode64
);
3185 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3187 MIPSInstr_Msa3R(MSA_CEQ
, MSA_D
, v_dst
, v_src
, v_dst
));
3188 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3192 vex_printf("iselV128Expr_wrk: Unsupported unop: %u\n", op_unop
);
3196 if (e
->tag
== Iex_Binop
) {
3197 IROp op_binop
= e
->Iex
.Binop
.op
;
3201 HReg v_dst
= newVRegV(env
);
3202 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3203 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3205 MIPSInstr_Msa3R(MSA_ADDV
, MSA_B
,
3206 v_dst
, v_src1
, v_src2
));
3211 HReg v_dst
= newVRegV(env
);
3212 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3213 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3215 MIPSInstr_Msa3R(MSA_ADDV
, MSA_H
,
3216 v_dst
, v_src1
, v_src2
));
3221 HReg v_dst
= newVRegV(env
);
3222 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3223 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3225 MIPSInstr_Msa3R(MSA_ADDV
, MSA_W
,
3226 v_dst
, v_src1
, v_src2
));
3231 HReg v_dst
= newVRegV(env
);
3232 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3233 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3235 MIPSInstr_Msa3R(MSA_ADDV
, MSA_D
,
3236 v_dst
, v_src1
, v_src2
));
3241 HReg v_dst
= newVRegV(env
);
3242 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3243 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3245 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
3246 v_dst
, v_src1
, v_src2
));
3251 HReg v_dst
= newVRegV(env
);
3252 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3253 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3255 MIPSInstr_Msa3R(MSA_SUBV
, MSA_H
,
3256 v_dst
, v_src1
, v_src2
));
3261 HReg v_dst
= newVRegV(env
);
3262 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3263 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3265 MIPSInstr_Msa3R(MSA_SUBV
, MSA_W
,
3266 v_dst
, v_src1
, v_src2
));
3271 HReg v_dst
= newVRegV(env
);
3272 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3273 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3275 MIPSInstr_Msa3R(MSA_SUBV
, MSA_D
,
3276 v_dst
, v_src1
, v_src2
));
3280 case Iop_QAdd8Sx16
: {
3281 HReg v_dst
= newVRegV(env
);
3282 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3283 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3285 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_B
,
3286 v_dst
, v_src1
, v_src2
));
3290 case Iop_QAdd16Sx8
: {
3291 HReg v_dst
= newVRegV(env
);
3292 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3293 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3295 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_H
,
3296 v_dst
, v_src1
, v_src2
));
3300 case Iop_QAdd32Sx4
: {
3301 HReg v_dst
= newVRegV(env
);
3302 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3303 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3305 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_W
,
3306 v_dst
, v_src1
, v_src2
));
3310 case Iop_QAdd64Sx2
: {
3311 HReg v_dst
= newVRegV(env
);
3312 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3313 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3315 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_D
,
3316 v_dst
, v_src1
, v_src2
));
3320 case Iop_QAdd8Ux16
: {
3321 HReg v_dst
= newVRegV(env
);
3322 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3323 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3325 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_B
,
3326 v_dst
, v_src1
, v_src2
));
3330 case Iop_QAdd16Ux8
: {
3331 HReg v_dst
= newVRegV(env
);
3332 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3333 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3335 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_H
,
3336 v_dst
, v_src1
, v_src2
));
3340 case Iop_QAdd32Ux4
: {
3341 HReg v_dst
= newVRegV(env
);
3342 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3343 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3345 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_W
,
3346 v_dst
, v_src1
, v_src2
));
3350 case Iop_QAdd64Ux2
: {
3351 HReg v_dst
= newVRegV(env
);
3352 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3353 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3355 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_D
,
3356 v_dst
, v_src1
, v_src2
));
3360 case Iop_QSub8Sx16
: {
3361 HReg v_dst
= newVRegV(env
);
3362 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3363 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3365 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_B
,
3366 v_dst
, v_src1
, v_src2
));
3370 case Iop_QSub16Sx8
: {
3371 HReg v_dst
= newVRegV(env
);
3372 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3373 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3375 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_H
,
3376 v_dst
, v_src1
, v_src2
));
3380 case Iop_QSub32Sx4
: {
3381 HReg v_dst
= newVRegV(env
);
3382 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3383 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3385 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_W
,
3386 v_dst
, v_src1
, v_src2
));
3390 case Iop_QSub64Sx2
: {
3391 HReg v_dst
= newVRegV(env
);
3392 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3393 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3395 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_D
,
3396 v_dst
, v_src1
, v_src2
));
3400 case Iop_QSub8Ux16
: {
3401 HReg v_dst
= newVRegV(env
);
3402 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3403 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3405 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_B
,
3406 v_dst
, v_src1
, v_src2
));
3410 case Iop_QSub16Ux8
: {
3411 HReg v_dst
= newVRegV(env
);
3412 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3413 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3415 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_H
,
3416 v_dst
, v_src1
, v_src2
));
3420 case Iop_QSub32Ux4
: {
3421 HReg v_dst
= newVRegV(env
);
3422 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3423 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3425 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_W
,
3426 v_dst
, v_src1
, v_src2
));
3430 case Iop_QSub64Ux2
: {
3431 HReg v_dst
= newVRegV(env
);
3432 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3433 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3435 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_D
,
3436 v_dst
, v_src1
, v_src2
));
3440 case Iop_QDMulHi32Sx4
: {
3441 HReg v_dst
= newVRegV(env
);
3442 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3443 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3445 MIPSInstr_Msa3RF(MSA_MUL_Q
, MSA_F_DW
,
3446 v_dst
, v_src1
, v_src2
));
3450 case Iop_QDMulHi16Sx8
: {
3451 HReg v_dst
= newVRegV(env
);
3452 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3453 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3455 MIPSInstr_Msa3RF(MSA_MUL_Q
, MSA_F_WH
,
3456 v_dst
, v_src1
, v_src2
));
3460 case Iop_QRDMulHi32Sx4
: {
3461 HReg v_dst
= newVRegV(env
);
3462 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3463 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3465 MIPSInstr_Msa3RF(MSA_MULR_Q
, MSA_F_DW
,
3466 v_dst
, v_src1
, v_src2
));
3470 case Iop_QRDMulHi16Sx8
: {
3471 HReg v_dst
= newVRegV(env
);
3472 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3473 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3475 MIPSInstr_Msa3RF(MSA_MULR_Q
, MSA_F_WH
,
3476 v_dst
, v_src1
, v_src2
));
3480 case Iop_Max8Sx16
: {
3481 HReg v_dst
= newVRegV(env
);
3482 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3483 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3485 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_B
,
3486 v_dst
, v_src1
, v_src2
));
3490 case Iop_Max16Sx8
: {
3491 HReg v_dst
= newVRegV(env
);
3492 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3493 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3495 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_H
,
3496 v_dst
, v_src1
, v_src2
));
3500 case Iop_Max32Sx4
: {
3501 HReg v_dst
= newVRegV(env
);
3502 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3503 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3505 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_W
,
3506 v_dst
, v_src1
, v_src2
));
3510 case Iop_Max64Sx2
: {
3511 HReg v_dst
= newVRegV(env
);
3512 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3513 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3515 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_D
,
3516 v_dst
, v_src1
, v_src2
));
3520 case Iop_Max8Ux16
: {
3521 HReg v_dst
= newVRegV(env
);
3522 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3523 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3525 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_B
,
3526 v_dst
, v_src1
, v_src2
));
3530 case Iop_Max16Ux8
: {
3531 HReg v_dst
= newVRegV(env
);
3532 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3533 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3535 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_H
,
3536 v_dst
, v_src1
, v_src2
));
3540 case Iop_Max32Ux4
: {
3541 HReg v_dst
= newVRegV(env
);
3542 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3543 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3545 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_W
,
3546 v_dst
, v_src1
, v_src2
));
3550 case Iop_Max64Ux2
: {
3551 HReg v_dst
= newVRegV(env
);
3552 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3553 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3555 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_D
,
3556 v_dst
, v_src1
, v_src2
));
3560 case Iop_Min8Sx16
: {
3561 HReg v_dst
= newVRegV(env
);
3562 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3563 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3565 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_B
,
3566 v_dst
, v_src1
, v_src2
));
3570 case Iop_Min16Sx8
: {
3571 HReg v_dst
= newVRegV(env
);
3572 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3573 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3575 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_H
,
3576 v_dst
, v_src1
, v_src2
));
3580 case Iop_Min32Sx4
: {
3581 HReg v_dst
= newVRegV(env
);
3582 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3583 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3585 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_W
,
3586 v_dst
, v_src1
, v_src2
));
3590 case Iop_Min64Sx2
: {
3591 HReg v_dst
= newVRegV(env
);
3592 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3593 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3595 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_D
,
3596 v_dst
, v_src1
, v_src2
));
3600 case Iop_Min8Ux16
: {
3601 HReg v_dst
= newVRegV(env
);
3602 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3603 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3605 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_B
,
3606 v_dst
, v_src1
, v_src2
));
3610 case Iop_Min16Ux8
: {
3611 HReg v_dst
= newVRegV(env
);
3612 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3613 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3615 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_H
,
3616 v_dst
, v_src1
, v_src2
));
3620 case Iop_Min32Ux4
: {
3621 HReg v_dst
= newVRegV(env
);
3622 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3623 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3625 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_W
,
3626 v_dst
, v_src1
, v_src2
));
3630 case Iop_Min64Ux2
: {
3631 HReg v_dst
= newVRegV(env
);
3632 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3633 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3635 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_D
,
3636 v_dst
, v_src1
, v_src2
));
3641 HReg v_dst
= newVRegV(env
);
3642 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3643 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3645 MIPSInstr_Msa3R(MSA_SLL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3650 HReg v_dst
= newVRegV(env
);
3651 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3652 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3654 MIPSInstr_Msa3R(MSA_SLL
, MSA_H
, v_dst
, v_src1
, v_src2
));
3659 HReg v_dst
= newVRegV(env
);
3660 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3661 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3663 MIPSInstr_Msa3R(MSA_SLL
, MSA_W
, v_dst
, v_src1
, v_src2
));
3668 HReg v_dst
= newVRegV(env
);
3669 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3670 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3672 MIPSInstr_Msa3R(MSA_SLL
, MSA_D
, v_dst
, v_src1
, v_src2
));
3677 HReg v_dst
= newVRegV(env
);
3678 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3679 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3681 MIPSInstr_Msa3R(MSA_SRL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3686 HReg v_dst
= newVRegV(env
);
3687 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3688 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3690 MIPSInstr_Msa3R(MSA_SRL
, MSA_H
, v_dst
, v_src1
, v_src2
));
3695 HReg v_dst
= newVRegV(env
);
3696 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3697 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3699 MIPSInstr_Msa3R(MSA_SRL
, MSA_W
, v_dst
, v_src1
, v_src2
));
3704 HReg v_dst
= newVRegV(env
);
3705 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3706 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3708 MIPSInstr_Msa3R(MSA_SRL
, MSA_D
, v_dst
, v_src1
, v_src2
));
3713 HReg v_dst
= newVRegV(env
);
3714 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3715 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3717 MIPSInstr_Msa3R(MSA_SRA
, MSA_B
, v_dst
, v_src1
, v_src2
));
3722 HReg v_dst
= newVRegV(env
);
3723 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3724 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3726 MIPSInstr_Msa3R(MSA_SRA
, MSA_H
, v_dst
, v_src1
, v_src2
));
3731 HReg v_dst
= newVRegV(env
);
3732 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3733 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3735 MIPSInstr_Msa3R(MSA_SRA
, MSA_W
, v_dst
, v_src1
, v_src2
));
3740 HReg v_dst
= newVRegV(env
);
3741 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3742 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3744 MIPSInstr_Msa3R(MSA_SRA
, MSA_D
, v_dst
, v_src1
, v_src2
));
3748 case Iop_InterleaveHI8x16
: {
3749 HReg v_dst
= newVRegV(env
);
3750 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3751 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3753 MIPSInstr_Msa3R(MSA_ILVL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3757 case Iop_InterleaveHI16x8
: {
3758 HReg v_dst
= newVRegV(env
);
3759 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3760 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3762 MIPSInstr_Msa3R(MSA_ILVL
, MSA_H
,
3763 v_dst
, v_src1
, v_src2
));
3767 case Iop_InterleaveHI32x4
: {
3768 HReg v_dst
= newVRegV(env
);
3769 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3770 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3772 MIPSInstr_Msa3R(MSA_ILVL
, MSA_W
,
3773 v_dst
, v_src1
, v_src2
));
3777 case Iop_InterleaveHI64x2
: {
3778 HReg v_dst
= newVRegV(env
);
3779 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3780 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3782 MIPSInstr_Msa3R(MSA_ILVL
, MSA_D
,
3783 v_dst
, v_src1
, v_src2
));
3787 case Iop_InterleaveLO8x16
: {
3788 HReg v_dst
= newVRegV(env
);
3789 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3790 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3792 MIPSInstr_Msa3R(MSA_ILVR
, MSA_B
,
3793 v_dst
, v_src1
, v_src2
));
3797 case Iop_InterleaveLO16x8
: {
3798 HReg v_dst
= newVRegV(env
);
3799 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3800 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3802 MIPSInstr_Msa3R(MSA_ILVR
, MSA_H
,
3803 v_dst
, v_src1
, v_src2
));
3807 case Iop_InterleaveLO32x4
: {
3808 HReg v_dst
= newVRegV(env
);
3809 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3810 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3812 MIPSInstr_Msa3R(MSA_ILVR
, MSA_W
,
3813 v_dst
, v_src1
, v_src2
));
3817 case Iop_InterleaveLO64x2
: {
3818 HReg v_dst
= newVRegV(env
);
3819 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3820 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3822 MIPSInstr_Msa3R(MSA_ILVR
, MSA_D
,
3823 v_dst
, v_src1
, v_src2
));
3827 case Iop_InterleaveEvenLanes8x16
: {
3828 HReg v_dst
= newVRegV(env
);
3829 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3830 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3832 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
,
3833 v_dst
, v_src1
, v_src2
));
3837 case Iop_InterleaveEvenLanes16x8
: {
3838 HReg v_dst
= newVRegV(env
);
3839 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3840 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3842 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
,
3843 v_dst
, v_src1
, v_src2
));
3847 case Iop_InterleaveEvenLanes32x4
: {
3848 HReg v_dst
= newVRegV(env
);
3849 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3850 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3852 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_W
,
3853 v_dst
, v_src1
, v_src2
));
3857 case Iop_InterleaveOddLanes8x16
: {
3858 HReg v_dst
= newVRegV(env
);
3859 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3860 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3862 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
,
3863 v_dst
, v_src1
, v_src2
));
3867 case Iop_InterleaveOddLanes16x8
: {
3868 HReg v_dst
= newVRegV(env
);
3869 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3870 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3872 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
,
3873 v_dst
, v_src1
, v_src2
));
3877 case Iop_InterleaveOddLanes32x4
: {
3878 HReg v_dst
= newVRegV(env
);
3879 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3880 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3882 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_W
,
3883 v_dst
, v_src1
, v_src2
));
3887 case Iop_PackEvenLanes8x16
: {
3888 HReg v_dst
= newVRegV(env
);
3889 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3890 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3892 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_B
,
3893 v_dst
, v_src1
, v_src2
));
3897 case Iop_PackEvenLanes16x8
: {
3898 HReg v_dst
= newVRegV(env
);
3899 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3900 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3902 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_H
,
3903 v_dst
, v_src1
, v_src2
));
3907 case Iop_PackEvenLanes32x4
: {
3908 HReg v_dst
= newVRegV(env
);
3909 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3910 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3912 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_W
,
3913 v_dst
, v_src1
, v_src2
));
3917 case Iop_PackOddLanes8x16
: {
3918 HReg v_dst
= newVRegV(env
);
3919 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3920 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3922 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_B
,
3923 v_dst
, v_src1
, v_src2
));
3927 case Iop_PackOddLanes16x8
: {
3928 HReg v_dst
= newVRegV(env
);
3929 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3930 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3932 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_H
,
3933 v_dst
, v_src1
, v_src2
));
3937 case Iop_PackOddLanes32x4
: {
3938 HReg v_dst
= newVRegV(env
);
3939 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3940 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3942 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_W
,
3943 v_dst
, v_src1
, v_src2
));
3947 case Iop_CmpEQ8x16
: {
3948 HReg v_dst
= newVRegV(env
);
3949 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3950 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3952 MIPSInstr_Msa3R(MSA_CEQ
, MSA_B
, v_dst
, v_src1
, v_src2
));
3956 case Iop_CmpEQ16x8
: {
3957 HReg v_dst
= newVRegV(env
);
3958 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3959 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3961 MIPSInstr_Msa3R(MSA_CEQ
, MSA_H
, v_dst
, v_src1
, v_src2
));
3965 case Iop_CmpEQ32x4
: {
3966 HReg v_dst
= newVRegV(env
);
3967 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3968 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3970 MIPSInstr_Msa3R(MSA_CEQ
, MSA_W
, v_dst
, v_src1
, v_src2
));
3974 case Iop_CmpEQ64x2
: {
3975 HReg v_dst
= newVRegV(env
);
3976 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3977 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3979 MIPSInstr_Msa3R(MSA_CEQ
, MSA_D
, v_dst
, v_src1
, v_src2
));
3983 case Iop_CmpGT8Sx16
: {
3984 HReg v_dst
= newVRegV(env
);
3985 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3986 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3988 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_B
,
3989 v_dst
, v_src2
, v_src1
));
3993 case Iop_CmpGT16Sx8
: {
3994 HReg v_dst
= newVRegV(env
);
3995 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3996 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3998 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_H
,
3999 v_dst
, v_src2
, v_src1
));
4003 case Iop_CmpGT32Sx4
: {
4004 HReg v_dst
= newVRegV(env
);
4005 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4006 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4008 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_W
,
4009 v_dst
, v_src2
, v_src1
));
4013 case Iop_CmpGT64Sx2
: {
4014 HReg v_dst
= newVRegV(env
);
4015 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4016 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4018 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_D
,
4019 v_dst
, v_src2
, v_src1
));
4023 case Iop_CmpGT8Ux16
: {
4024 HReg v_dst
= newVRegV(env
);
4025 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4026 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4028 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_B
,
4029 v_dst
, v_src2
, v_src1
));
4033 case Iop_CmpGT16Ux8
: {
4034 HReg v_dst
= newVRegV(env
);
4035 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4036 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4038 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_H
,
4039 v_dst
, v_src2
, v_src1
));
4043 case Iop_CmpGT32Ux4
: {
4044 HReg v_dst
= newVRegV(env
);
4045 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4046 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4048 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_W
,
4049 v_dst
, v_src2
, v_src1
));
4053 case Iop_CmpGT64Ux2
: {
4054 HReg v_dst
= newVRegV(env
);
4055 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4056 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4058 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_D
,
4059 v_dst
, v_src2
, v_src1
));
4063 case Iop_Avg8Sx16
: {
4064 HReg v_dst
= newVRegV(env
);
4065 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4066 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4068 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_B
,
4069 v_dst
, v_src1
, v_src2
));
4073 case Iop_Avg16Sx8
: {
4074 HReg v_dst
= newVRegV(env
);
4075 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4076 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4078 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_H
,
4079 v_dst
, v_src1
, v_src2
));
4083 case Iop_Avg32Sx4
: {
4084 HReg v_dst
= newVRegV(env
);
4085 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4086 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4088 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_W
,
4089 v_dst
, v_src1
, v_src2
));
4093 case Iop_Avg8Ux16
: {
4094 HReg v_dst
= newVRegV(env
);
4095 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4096 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4098 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_B
,
4099 v_dst
, v_src1
, v_src2
));
4103 case Iop_Avg16Ux8
: {
4104 HReg v_dst
= newVRegV(env
);
4105 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4106 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4108 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_H
,
4109 v_dst
, v_src1
, v_src2
));
4113 case Iop_Avg32Ux4
: {
4114 HReg v_dst
= newVRegV(env
);
4115 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4116 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4118 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_W
,
4119 v_dst
, v_src1
, v_src2
));
4124 HReg v_dst
= newVRegV(env
);
4125 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4126 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4128 MIPSInstr_Msa3R(MSA_MULV
, MSA_B
,
4129 v_dst
, v_src1
, v_src2
));
4134 HReg v_dst
= newVRegV(env
);
4135 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4136 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4138 MIPSInstr_Msa3R(MSA_MULV
, MSA_H
,
4139 v_dst
, v_src1
, v_src2
));
4144 HReg v_dst
= newVRegV(env
);
4145 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4146 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4148 MIPSInstr_Msa3R(MSA_MULV
, MSA_W
,
4149 v_dst
, v_src1
, v_src2
));
4154 HReg v_dst
= newVRegV(env
);
4155 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4156 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4157 addInstr(env
, MIPSInstr_MsaVec(MSA_ANDV
, v_dst
, v_src1
, v_src2
));
4162 HReg v_dst
= newVRegV(env
);
4163 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4164 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4165 addInstr(env
, MIPSInstr_MsaVec(MSA_ORV
, v_dst
, v_src1
, v_src2
));
4170 HReg v_dst
= newVRegV(env
);
4171 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4172 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4173 addInstr(env
, MIPSInstr_MsaVec(MSA_XORV
, v_dst
, v_src1
, v_src2
));
4178 HReg v_dst
= newVRegV(env
);
4179 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4181 sm
= iselWordExpr_RH7u(env
, e
->Iex
.Binop
.arg2
);
4183 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
4184 v_dst
, v_src1
, v_src1
));
4186 if (sm
->tag
== Mrh_Imm
) {
4187 int n
= (sm
->Mrh
.Imm
.imm16
) >> 3;
4189 MIPSInstr_MsaElm(MSA_SLDI
, v_src1
, v_dst
,
4192 HReg v_src2
= sm
->Mrh
.Reg
.reg
;
4193 MIPSRH
*ri
= MIPSRH_Imm(False
, 3);
4194 HReg r_dst
= newVRegI(env
);
4195 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/*32bit shift */,
4196 r_dst
, v_src2
, ri
));
4198 MIPSInstr_Msa3R(MSA_SLD
, MSA_B
,
4199 v_dst
, v_src1
, r_dst
));
4206 HReg v_dst
= newVRegV(env
);
4207 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4209 sm
= iselWordExpr_RH7u(env
, e
->Iex
.Binop
.arg2
);
4211 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
4212 v_dst
, v_src1
, v_src1
));
4214 if (sm
->tag
== Mrh_Imm
) {
4215 int n
= 16 - ((sm
->Mrh
.Imm
.imm16
) >> 3);
4220 MIPSInstr_MsaElm(MSA_SLDI
, v_dst
, v_src1
,
4223 HReg v_src2
= sm
->Mrh
.Reg
.reg
;
4224 MIPSRH
*ri
= MIPSRH_Imm(False
, 3);
4225 HReg r_dst
= newVRegI(env
);
4226 HReg help
= newVRegI(env
);
4227 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, help
, v_src2
, sm
));
4228 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, help
, help
, sm
));
4229 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/*32bit shift */,
4232 MIPSInstr_Msa3R(MSA_SLD
, MSA_B
,
4233 v_src1
, v_dst
, r_dst
));
4239 case Iop_ShlN8x16
: {
4240 HReg v_dst
= newVRegV(env
);
4241 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4242 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4243 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4244 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4246 MIPSInstr_MsaBit(MSA_SLLI
, MSA_B
,
4247 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4252 case Iop_ShlN16x8
: {
4253 HReg v_dst
= newVRegV(env
);
4254 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4255 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4256 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4257 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4259 MIPSInstr_MsaBit(MSA_SLLI
, MSA_H
,
4260 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4265 case Iop_ShlN32x4
: {
4266 HReg v_dst
= newVRegV(env
);
4267 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4268 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4269 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4270 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4272 MIPSInstr_MsaBit(MSA_SLLI
, MSA_W
,
4273 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4278 case Iop_ShlN64x2
: {
4279 HReg v_dst
= newVRegV(env
);
4280 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4281 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4282 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4283 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4285 MIPSInstr_MsaBit(MSA_SLLI
, MSA_D
,
4286 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4291 case Iop_SarN8x16
: {
4292 HReg v_dst
= newVRegV(env
);
4293 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4294 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4295 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4296 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4298 MIPSInstr_MsaBit(MSA_SRAI
, MSA_B
,
4299 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4304 case Iop_SarN16x8
: {
4305 HReg v_dst
= newVRegV(env
);
4306 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4307 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4308 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4309 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4311 MIPSInstr_MsaBit(MSA_SRAI
, MSA_H
,
4312 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4317 case Iop_SarN32x4
: {
4318 HReg v_dst
= newVRegV(env
);
4319 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4320 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4321 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4322 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4324 MIPSInstr_MsaBit(MSA_SRAI
, MSA_W
,
4325 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4330 case Iop_SarN64x2
: {
4331 HReg v_dst
= newVRegV(env
);
4332 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4333 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4334 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4335 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4337 MIPSInstr_MsaBit(MSA_SRAI
, MSA_D
,
4338 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4343 case Iop_ShrN8x16
: {
4344 HReg v_dst
= newVRegV(env
);
4345 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4346 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4347 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4348 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4350 MIPSInstr_MsaBit(MSA_SRLI
, MSA_B
,
4351 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4356 case Iop_ShrN16x8
: {
4357 HReg v_dst
= newVRegV(env
);
4358 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4359 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4360 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4361 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4363 MIPSInstr_MsaBit(MSA_SRLI
, MSA_H
,
4364 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4369 case Iop_ShrN32x4
: {
4370 HReg v_dst
= newVRegV(env
);
4371 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4372 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4373 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4374 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4376 MIPSInstr_MsaBit(MSA_SRLI
, MSA_W
,
4377 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4382 case Iop_ShrN64x2
: {
4383 HReg v_dst
= newVRegV(env
);
4384 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4385 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4386 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4387 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4389 MIPSInstr_MsaBit(MSA_SRLI
, MSA_D
,
4390 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4395 case Iop_QandQSarNnarrow64Sto32Sx2
: {
4396 HReg v_dst
= newVRegV(env
);
4397 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4398 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4399 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4400 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4402 MIPSInstr_MsaBit(MSA_SRAI
, MSA_D
,
4403 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4405 addInstr(env
, MIPSInstr_MsaBit(MSA_SAT_S
, MSA_D
, 31, v_dst
, v_dst
));
4409 case Iop_QandQSarNnarrow32Sto16Sx4
: {
4410 HReg v_dst
= newVRegV(env
);
4411 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4412 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4413 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4414 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4416 MIPSInstr_MsaBit(MSA_SRAI
, MSA_W
,
4417 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4420 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_W
, 15, v_dst
, v_dst
));
4424 case Iop_QandQRSarNnarrow64Sto32Sx2
: {
4425 HReg v_dst
= newVRegV(env
);
4426 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4427 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4428 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4429 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4431 MIPSInstr_MsaBit(MSA_SRARI
, MSA_D
,
4432 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4435 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_D
, 31, v_dst
, v_dst
));
4439 case Iop_QandQRSarNnarrow32Sto16Sx4
: {
4440 HReg v_dst
= newVRegV(env
);
4441 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4442 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4443 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4444 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4446 MIPSInstr_MsaBit(MSA_SRARI
, MSA_W
,
4447 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4450 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_W
, 15, v_dst
, v_dst
));
4454 case Iop_CmpEQ32Fx4
: {
4455 HReg v_dst
= newVRegV(env
);
4456 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4457 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4459 MIPSInstr_Msa3RF(MSA_FCEQ
, MSA_F_WH
,
4460 v_dst
, v_src1
, v_src2
));
4464 case Iop_CmpEQ64Fx2
: {
4465 HReg v_dst
= newVRegV(env
);
4466 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4467 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4469 MIPSInstr_Msa3RF(MSA_FCEQ
, MSA_F_DW
,
4470 v_dst
, v_src1
, v_src2
));
4474 case Iop_CmpLT32Fx4
: {
4475 HReg v_dst
= newVRegV(env
);
4476 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4477 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4479 MIPSInstr_Msa3RF(MSA_FCLT
, MSA_F_WH
,
4480 v_dst
, v_src1
, v_src2
));
4484 case Iop_CmpLT64Fx2
: {
4485 HReg v_dst
= newVRegV(env
);
4486 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4487 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4489 MIPSInstr_Msa3RF(MSA_FCLT
, MSA_F_DW
,
4490 v_dst
, v_src1
, v_src2
));
4494 case Iop_CmpLE32Fx4
: {
4495 HReg v_dst
= newVRegV(env
);
4496 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4497 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4499 MIPSInstr_Msa3RF(MSA_FCLE
, MSA_F_WH
,
4500 v_dst
, v_src1
, v_src2
));
4504 case Iop_CmpLE64Fx2
: {
4505 HReg v_dst
= newVRegV(env
);
4506 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4507 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4509 MIPSInstr_Msa3RF(MSA_FCLE
, MSA_F_DW
,
4510 v_dst
, v_src1
, v_src2
));
4514 case Iop_CmpUN32Fx4
: {
4515 HReg v_dst
= newVRegV(env
);
4516 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4517 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4519 MIPSInstr_Msa3RF(MSA_FCUN
, MSA_F_WH
,
4520 v_dst
, v_src1
, v_src2
));
4524 case Iop_CmpUN64Fx2
: {
4525 HReg v_dst
= newVRegV(env
);
4526 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4527 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4529 MIPSInstr_Msa3RF(MSA_FCUN
, MSA_F_DW
,
4530 v_dst
, v_src1
, v_src2
));
4534 case Iop_64HLtoV128
: {
4535 HReg v_dst
= newVRegV(env
);
4540 r_src1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4541 r_src2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4543 MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src2
, v_dst
));
4545 MIPSInstr_MsaElm(MSA_INSERT
, r_src1
, v_dst
,
4548 HReg r_src1h
, r_src1l
;
4549 HReg r_src2h
, r_src2l
;
4550 iselInt64Expr(&r_src1h
, &r_src1l
, env
, e
->Iex
.Binop
.arg1
);
4551 iselInt64Expr(&r_src2h
, &r_src2l
, env
, e
->Iex
.Binop
.arg2
);
4553 MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_src2l
, v_dst
));
4555 MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, v_dst
,
4558 MIPSInstr_MsaElm(MSA_INSERT
, r_src1l
, v_dst
,
4561 MIPSInstr_MsaElm(MSA_INSERT
, r_src1h
, v_dst
,
4568 case Iop_Min32Fx4
: {
4569 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4570 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4571 HReg v_dst
= newVRegV(env
);
4573 MIPSInstr_Msa3RF(MSA_FMIN
, MSA_F_WH
,
4574 v_dst
, v_src1
, v_src2
));
4578 case Iop_Min64Fx2
: {
4579 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4580 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4581 HReg v_dst
= newVRegV(env
);
4583 MIPSInstr_Msa3RF(MSA_FMIN
, MSA_F_DW
,
4584 v_dst
, v_src1
, v_src2
));
4588 case Iop_Max32Fx4
: {
4589 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4590 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4591 HReg v_dst
= newVRegV(env
);
4593 MIPSInstr_Msa3RF(MSA_FMAX
, MSA_F_WH
,
4594 v_dst
, v_src1
, v_src2
));
4598 case Iop_Max64Fx2
: {
4599 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4600 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4601 HReg v_dst
= newVRegV(env
);
4603 MIPSInstr_Msa3RF(MSA_FMAX
, MSA_F_DW
,
4604 v_dst
, v_src1
, v_src2
));
4608 case Iop_Sqrt32Fx4
: {
4609 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4610 HReg v_dst
= newVRegV(env
);
4611 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
4613 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_WH
, v_dst
, v_src
));
4614 set_MIPS_rounding_default_MSA(env
);
4618 case Iop_Sqrt64Fx2
: {
4619 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4620 HReg v_dst
= newVRegV(env
);
4621 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
4623 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_DW
, v_dst
, v_src
));
4624 set_MIPS_rounding_default_MSA(env
);
4629 vex_printf("iselV128Expr_wrk: unsupported binop: %x\n", op_binop
);
4633 if (e
->tag
== Iex_Triop
) {
4634 IROp op_triop
= e
->Iex
.Triop
.details
->op
;
4637 case Iop_Add32Fx4
: {
4638 HReg v_dst
= newVRegV(env
);
4639 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4640 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4641 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4643 MIPSInstr_Msa3RF(MSA_FADD
, MSA_F_WH
,
4644 v_dst
, v_src1
, v_src2
));
4645 set_MIPS_rounding_default_MSA(env
);
4649 case Iop_Add64Fx2
: {
4650 HReg v_dst
= newVRegV(env
);
4651 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4652 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4653 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4655 MIPSInstr_Msa3RF(MSA_FADD
, MSA_F_DW
,
4656 v_dst
, v_src1
, v_src2
));
4657 set_MIPS_rounding_default_MSA(env
);
4661 case Iop_Sub32Fx4
: {
4662 HReg v_dst
= newVRegV(env
);
4663 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4664 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4665 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4667 MIPSInstr_Msa3RF(MSA_FSUB
, MSA_F_WH
,
4668 v_dst
, v_src1
, v_src2
));
4669 set_MIPS_rounding_default_MSA(env
);
4673 case Iop_Sub64Fx2
: {
4674 HReg v_dst
= newVRegV(env
);
4675 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4676 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4677 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4679 MIPSInstr_Msa3RF(MSA_FSUB
, MSA_F_DW
,
4680 v_dst
, v_src1
, v_src2
));
4681 set_MIPS_rounding_default_MSA(env
);
4685 case Iop_Mul32Fx4
: {
4686 HReg v_dst
= newVRegV(env
);
4687 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4688 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4689 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4691 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_WH
,
4692 v_dst
, v_src1
, v_src2
));
4693 set_MIPS_rounding_default_MSA(env
);
4697 case Iop_Mul64Fx2
: {
4698 HReg v_dst
= newVRegV(env
);
4699 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4700 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4701 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4703 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_DW
,
4704 v_dst
, v_src1
, v_src2
));
4705 set_MIPS_rounding_default_MSA(env
);
4709 case Iop_Div32Fx4
: {
4710 HReg v_dst
= newVRegV(env
);
4711 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4712 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4713 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4715 MIPSInstr_Msa3RF(MSA_FDIV
, MSA_F_WH
,
4716 v_dst
, v_src1
, v_src2
));
4717 set_MIPS_rounding_default_MSA(env
);
4721 case Iop_Div64Fx2
: {
4722 HReg v_dst
= newVRegV(env
);
4723 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4724 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4725 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4727 MIPSInstr_Msa3RF(MSA_FDIV
, MSA_F_DW
,
4728 v_dst
, v_src1
, v_src2
));
4729 set_MIPS_rounding_default_MSA(env
);
4733 case Iop_F32x4_2toQ16x8
: {
4734 HReg v_dst
= newVRegV(env
);
4735 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4736 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4737 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4739 MIPSInstr_Msa3RF(MSA_FTQ
, MSA_F_WH
,
4740 v_dst
, v_src1
, v_src2
));
4741 set_MIPS_rounding_default_MSA(env
);
4745 case Iop_F64x2_2toQ32x4
: {
4746 HReg v_dst
= newVRegV(env
);
4747 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4748 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4749 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4751 MIPSInstr_Msa3RF(MSA_FTQ
, MSA_F_DW
,
4752 v_dst
, v_src1
, v_src2
));
4753 set_MIPS_rounding_default_MSA(env
);
4757 case Iop_Scale2_32Fx4
: {
4758 HReg v_dst
= newVRegV(env
);
4759 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4760 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4761 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4763 MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_WH
,
4764 v_dst
, v_src1
, v_src2
));
4765 set_MIPS_rounding_default_MSA(env
);
4769 case Iop_Scale2_64Fx2
: {
4770 HReg v_dst
= newVRegV(env
);
4771 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4772 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4773 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4775 MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
,
4776 v_dst
, v_src1
, v_src2
));
4777 set_MIPS_rounding_default_MSA(env
);
4782 vex_printf("iselV128Expr_wrk: unsupported triop: %x\n", op_triop
);
4786 if (e
->tag
== Iex_Const
) {
4787 IRConst
*con
= e
->Iex
.Const
.con
;
4789 if (con
->tag
!= Ico_V128
) {
4790 vpanic("iselV128Expr.const(mips)");
4792 HReg v_dst
= newVRegV(env
);
4793 UShort val
= con
->Ico
.V128
;
4794 HReg zero
= Zero(mode64
);
4797 case 0: /* likely */
4798 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
4802 HReg r_tmp
= newVRegI(env
);
4804 addInstr(env
, MIPSInstr_LI(r_tmp
, 0xfful
));
4808 MIPSInstr_Msa2R(MSA_FILL
, MSA_B
, r_tmp
, v_dst
));
4811 MIPSInstr_Msa2R(MSA_FILL
, MSA_B
, zero
, v_dst
));
4814 for (i
= 1; i
< 16; i
++) {
4819 MIPSInstr_MsaElm(MSA_INSERT
, r_tmp
, v_dst
,
4823 MIPSInstr_MsaElm(MSA_INSERT
, zero
, v_dst
,
4836 if (e
->tag
== Iex_ITE
) {
4837 HReg v_dst
= newVRegV(env
);
4838 HReg iff
= iselV128Expr(env
, e
->Iex
.ITE
.iffalse
);
4839 HReg ift
= iselV128Expr(env
, e
->Iex
.ITE
.iftrue
);
4840 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
4841 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_cond
, r_cond
,
4842 MIPSRH_Imm(False
, 1)));
4843 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_cond
, v_dst
));
4845 MIPSInstr_Alu(Malu_ADD
, r_cond
, r_cond
, MIPSRH_Imm(True
, 1)));
4846 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_cond
, v_dst
, MSA_DFN_W
| 2));
4847 addInstr(env
, MIPSInstr_Msa3R(MSA_VSHF
, MSA_D
, v_dst
, ift
, iff
));
4851 vex_printf("iselV128Expr_wrk: Unsupported tag: %x\n", e
->tag
);
4853 vpanic("iselV128Expr(mips)");
4856 /*---------------------------------------------------------*/
4857 /*--- ISEL: Integer expressions (128 bit) ---*/
4858 /*---------------------------------------------------------*/
4860 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
4861 which is returned as the first two parameters. As with
4862 iselWordExpr_R, these may be either real or virtual regs; in any
4863 case they must not be changed by subsequent code emitted by the
4866 static void iselInt128Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4868 vassert(env
->mode64
);
4869 iselInt128Expr_wrk(rHi
, rLo
, env
, e
);
4870 vassert(hregClass(*rHi
) == HRcGPR(env
->mode64
));
4871 vassert(hregIsVirtual(*rHi
));
4872 vassert(hregClass(*rLo
) == HRcGPR(env
->mode64
));
4873 vassert(hregIsVirtual(*rLo
));
4876 /* DO NOT CALL THIS DIRECTLY ! */
4877 static void iselInt128Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
,
4881 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I128
);
4883 /* read 128-bit IRTemp */
4884 if (e
->tag
== Iex_RdTmp
) {
4885 lookupIRTempPair(rHi
, rLo
, env
, e
->Iex
.RdTmp
.tmp
);
4889 /* --------- BINARY ops --------- */
4890 if (e
->tag
== Iex_Binop
) {
4891 switch (e
->Iex
.Binop
.op
) {
4892 /* 64 x 64 -> 128 multiply */
4895 HReg tLo
= newVRegI(env
);
4896 HReg tHi
= newVRegI(env
);
4897 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_MullS64
);
4898 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4899 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4900 #if (__mips_isa_rev >= 6)
4901 addInstr(env
, MIPSInstr_Mulr6(syned
, False
, True
,
4902 tLo
, r_srcL
, r_srcR
));
4903 addInstr(env
, MIPSInstr_Mulr6(syned
, False
, False
,
4904 tHi
, r_srcL
, r_srcR
));
4906 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
4907 addInstr(env
, MIPSInstr_Mfhi(tHi
));
4908 addInstr(env
, MIPSInstr_Mflo(tLo
));
4915 /* 64HLto128(e1,e2) */
4917 *rHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4918 *rLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4921 case Iop_DivModU64to64
:
4922 case Iop_DivModS64to64
: {
4923 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4924 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4925 HReg tLo
= newVRegI(env
);
4926 HReg tHi
= newVRegI(env
);
4927 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS64to64
);
4928 #if (__mips_isa_rev >= 6)
4929 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
4930 False
/*32bit or 64bit div */ ,
4932 tLo
, r_srcL
, r_srcR
));
4933 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
4934 False
/*32bit or 64bit div */ ,
4936 tHi
, r_srcL
, r_srcR
));
4938 addInstr(env
, MIPSInstr_Div(syned
, False
, r_srcL
, r_srcR
));
4939 addInstr(env
, MIPSInstr_Mfhi(tHi
));
4940 addInstr(env
, MIPSInstr_Mflo(tLo
));
4951 vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e
->tag
);
4953 vpanic("iselInt128Expr(mips64)");
4956 /*---------------------------------------------------------*/
4957 /*--- ISEL: Integer expressions (64 bit) ---*/
4958 /*---------------------------------------------------------*/
4960 /* 32-bit mode ONLY. Compute a 64-bit value into the register
4961 * pair HI, LO. HI and LO must not be changed by subsequent
4962 * code emitted by the caller. */
4964 static void iselInt64Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4966 vassert(!env
->mode64
);
4967 iselInt64Expr_wrk(rHi
, rLo
, env
, e
);
4968 vassert(hregClass(*rHi
) == HRcInt32
);
4969 vassert(hregIsVirtual(*rHi
));
4970 vassert(hregClass(*rLo
) == HRcInt32
);
4971 vassert(hregIsVirtual(*rLo
));
4974 /* DO NOT CALL THIS DIRECTLY ! */
4975 static void iselInt64Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4978 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I64
);
4980 /* read 64-bit IRTemp */
4981 if (e
->tag
== Iex_RdTmp
) {
4982 lookupIRTemp64(rHi
, rLo
, env
, e
->Iex
.RdTmp
.tmp
);
4986 if (e
->tag
== Iex_Load
) {
4987 HReg tLo
= newVRegI(env
);
4988 HReg tHi
= newVRegI(env
);
4989 HReg r_addr
= iselWordExpr_R(env
, e
->Iex
.Load
.addr
);
4990 addInstr(env
, MIPSInstr_Load(4, tHi
, MIPSAMode_IR(0, r_addr
), mode64
));
4991 addInstr(env
, MIPSInstr_Load(4, tLo
, MIPSAMode_IR(4, r_addr
), mode64
));
4997 /* 64-bit literal */
4998 if (e
->tag
== Iex_Const
) {
4999 ULong w64
= e
->Iex
.Const
.con
->Ico
.U64
;
5000 UInt wHi
= toUInt(w64
>> 32);
5001 UInt wLo
= toUInt(w64
);
5002 HReg tLo
= newVRegI(env
);
5003 HReg tHi
= newVRegI(env
);
5004 vassert(e
->Iex
.Const
.con
->tag
== Ico_U64
);
5007 /* Save a precious Int register in this special case. */
5008 addInstr(env
, MIPSInstr_LI(tLo
, (ULong
) wLo
));
5012 addInstr(env
, MIPSInstr_LI(tHi
, (ULong
) wHi
));
5013 addInstr(env
, MIPSInstr_LI(tLo
, (ULong
) wLo
));
5022 if (e
->tag
== Iex_Get
) {
5023 HReg tLo
= newVRegI(env
);
5024 HReg tHi
= newVRegI(env
);
5026 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
5027 GuestStatePointer(mode64
));
5028 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5029 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeInt(am_addr
), mode64
));
5036 if (e
->tag
== Iex_ITE
) {
5037 vassert(typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
);
5038 HReg expr0Lo
, expr0Hi
;
5039 HReg expr1Lo
, expr1Hi
;
5040 HReg desLo
= newVRegI(env
);
5041 HReg desHi
= newVRegI(env
);
5042 HReg cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
5044 /* expr0Hi:expr0Lo = iffalse */
5045 /* expr1Hi:expr1Lo = iftrue */
5046 iselInt64Expr(&expr0Hi
, &expr0Lo
, env
, e
->Iex
.ITE
.iffalse
);
5047 iselInt64Expr(&expr1Hi
, &expr1Lo
, env
, e
->Iex
.ITE
.iftrue
);
5049 /* move desLo, expr0Lo
5050 * move desHi, expr0Hi
5051 * movn desLo, expr1Lo, cond
5052 * movn desHi, expr1Hi, cond */
5053 #if (__mips_isa_rev >= 6)
5055 HReg r_temp
= newVRegI(env
);
5056 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, desLo
, expr0Lo
, cond
));
5057 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, expr1Lo
, cond
));
5058 addInstr(env
, MIPSInstr_Alu(Malu_OR
, desLo
, desLo
, MIPSRH_Reg(r_temp
)));
5060 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, desHi
, expr0Hi
, cond
));
5061 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, expr1Hi
, cond
));
5062 addInstr(env
, MIPSInstr_Alu(Malu_OR
, desHi
, desHi
, MIPSRH_Reg(r_temp
)));
5065 addInstr(env
, mk_iMOVds_RR(desLo
, expr0Lo
));
5066 addInstr(env
, mk_iMOVds_RR(desHi
, expr0Hi
));
5067 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, desLo
, expr1Lo
, cond
));
5068 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, desHi
, expr1Hi
, cond
));
5076 if (e
->tag
== Iex_CCall
) {
5077 HReg r_dstH
= newVRegI(env
);
5078 HReg r_dstL
= newVRegI(env
);
5079 vassert(e
->Iex
.CCall
.retty
== Ity_I64
);
5081 /* Marshal args, do the call, clear stack. */
5083 RetLoc rloc
= mk_RetLoc_INVALID();
5084 doHelperCall(&addToSp
, &rloc
, env
, NULL
/*guard*/, e
->Iex
.CCall
.cee
,
5085 e
->Iex
.CCall
.retty
, e
->Iex
.CCall
.args
);
5087 vassert(is_sane_RetLoc(rloc
));
5088 vassert(rloc
.pri
== RLPri_2Int
);
5089 vassert(addToSp
== 0);
5090 addInstr(env
, mk_iMOVds_RR(r_dstL
, hregMIPS_GPR2(False
)));
5091 addInstr(env
, mk_iMOVds_RR(r_dstH
, hregMIPS_GPR3(False
)));
5097 /* --------- BINARY ops --------- */
5098 if (e
->tag
== Iex_Binop
) {
5099 IROp op_binop
= e
->Iex
.Binop
.op
;
5101 /* 32 x 32 -> 64 multiply */
5104 HReg xLo
, xHi
, yLo
, yHi
, carryBit
;
5106 HReg tHi
= newVRegI(env
);
5107 HReg tHi1
= newVRegI(env
);
5108 HReg tLo
= newVRegI(env
);
5110 carryBit
= newVRegI(env
);
5113 MIPSCondCode cc
= MIPScc_LO
;
5115 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5116 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5117 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5120 addInstr(env
, MIPSInstr_Cmp(False
, size32
, carryBit
, tLo
, xLo
, cc
));
5122 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi1
, xHi
, MIPSRH_Reg(yHi
)));
5123 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, tHi1
,
5124 MIPSRH_Reg(carryBit
)));
5131 HReg xLo
, xHi
, yLo
, yHi
, borrow
;
5133 MIPSCondCode cc
= MIPScc_LO
;
5135 HReg tHi
= newVRegI(env
);
5136 HReg tLo
= newVRegI(env
);
5138 borrow
= newVRegI(env
);
5140 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5141 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5143 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5145 /* Check if borrow is nedded. */
5146 addInstr(env
, MIPSInstr_Cmp(False
, size32
, borrow
, xLo
, yLo
, cc
));
5148 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, yHi
, yHi
,
5149 MIPSRH_Reg(borrow
)));
5150 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tHi
, xHi
, MIPSRH_Reg(yHi
)));
5158 HReg tLo
= newVRegI(env
);
5159 HReg tHi
= newVRegI(env
);
5160 Bool syned
= toBool(op_binop
== Iop_MullS32
);
5161 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5162 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5163 #if (__mips_isa_rev >= 6)
5164 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, True
,
5165 tLo
, r_srcL
, r_srcR
));
5166 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, False
,
5167 tHi
, r_srcL
, r_srcR
));
5169 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
5170 addInstr(env
, MIPSInstr_Mfhi(tHi
));
5171 addInstr(env
, MIPSInstr_Mflo(tLo
));
5179 case Iop_DivModU32to32
:
5180 case Iop_DivModS32to32
: {
5181 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5182 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5183 HReg tLo
= newVRegI(env
);
5184 HReg tHi
= newVRegI(env
);
5185 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS32to32
);
5187 #if (__mips_isa_rev >= 6)
5188 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
5189 True
/*32bit or 64bit div */ ,
5191 tLo
, r_srcL
, r_srcR
));
5192 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
5193 True
/*32bit or 64bit div */ ,
5195 tHi
, r_srcL
, r_srcR
));
5197 addInstr(env
, MIPSInstr_Div(syned
, True
, r_srcL
, r_srcR
));
5198 addInstr(env
, MIPSInstr_Mfhi(tHi
));
5199 addInstr(env
, MIPSInstr_Mflo(tLo
));
5206 /* 32HLto64(e1,e2) */
5208 *rHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5209 *rLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5212 /* Or64/And64/Xor64 */
5216 HReg xLo
, xHi
, yLo
, yHi
;
5217 HReg tLo
= newVRegI(env
);
5218 HReg tHi
= newVRegI(env
);
5219 MIPSAluOp op
= (op_binop
== Iop_Or64
) ? Malu_OR
:
5220 (op_binop
== Iop_And64
) ? Malu_AND
: Malu_XOR
;
5221 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5222 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5223 addInstr(env
, MIPSInstr_Alu(op
, tHi
, xHi
, MIPSRH_Reg(yHi
)));
5224 addInstr(env
, MIPSInstr_Alu(op
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5231 /* 64-bit logical shift right based on what gcc generates:
5244 HReg r_srcLo
, r_srcHi
;
5245 HReg r_srcLotmp
= newVRegI(env
);
5246 HReg shift
= newVRegI(env
);
5247 HReg a3
= newVRegI(env
);
5248 HReg r_dstLo
= newVRegI(env
);
5249 HReg r_dstHi
= newVRegI(env
);
5250 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5253 iselInt64Expr(&r_srcHi
, &r_srcLo
, env
, e
->Iex
.Binop
.arg1
);
5254 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5256 if (sa
->tag
== Mrh_Imm
) {
5257 addInstr(env
, MIPSInstr_LI(shift
, sa
->Mrh
.Imm
.imm16
));
5260 addInstr(env
, MIPSInstr_Alu(Malu_AND
, shift
, sa
->Mrh
.Reg
.reg
,
5261 MIPSRH_Imm(False
, 0x3f)));
5263 /* nor r_dstLo, zero, shift */
5264 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(shift
)));
5265 /* sll a3, r_srcHi, 0x1 */
5266 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5267 a3
, r_srcHi
, MIPSRH_Imm(False
, 0x1)));
5268 /* sllv a3, a3, r_dstLo */
5269 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5270 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5271 /* srlv r_dstLo, r_srcLo, shift */
5272 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5273 r_dstLo
, r_srcLo
, MIPSRH_Reg(shift
)));
5274 /* srlv r_dstHi, r_srcHi, shift */
5275 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5276 r_dstHi
, r_srcHi
, MIPSRH_Reg(shift
)));
5277 /* andi r_srcLo, shift, 0x20 */
5278 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcLotmp
, shift
,
5279 MIPSRH_Imm(False
, 0x20)));
5280 /* or r_dstLo, a3, r_dstLo */
5281 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, a3
, MIPSRH_Reg(r_dstLo
)));
5282 #if (__mips_isa_rev >= 6)
5283 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, r_srcLotmp
));
5284 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_dstHi
, r_srcLotmp
));
5285 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, r_dstLo
, MIPSRH_Reg(a3
)));
5287 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, r_srcLotmp
));
5289 /* movn r_dstLo, r_dstHi, r_srcLo */
5290 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, r_dstHi
, r_srcLotmp
));
5291 /* movn r_dstHi, zero, r_srcLo */
5292 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, zero
, r_srcLotmp
));
5300 /* 64-bit shift left based on what gcc generates:
5314 HReg r_srcLo
, r_srcHi
;
5315 HReg r_shift
= newVRegI(env
);
5316 HReg a3
= newVRegI(env
);
5317 HReg r_dstLo
= newVRegI(env
);
5318 HReg r_dstHi
= newVRegI(env
);
5319 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5322 iselInt64Expr(&r_srcHi
, &r_srcLo
, env
, e
->Iex
.Binop
.arg1
);
5323 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5325 if (sa
->tag
== Mrh_Imm
) {
5326 addInstr(env
, MIPSInstr_LI(r_shift
, sa
->Mrh
.Imm
.imm16
));
5329 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_shift
, sa
->Mrh
.Reg
.reg
,
5330 MIPSRH_Imm(False
, 0x3f)));
5332 /* nor r_dstLo, zero, r_shift */
5333 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(r_shift
)));
5334 /* srl a3, r_srcLo, 0x1 */
5335 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5336 a3
, r_srcLo
, MIPSRH_Imm(False
, 0x1)));
5337 /* srlv a3, a3, r_dstLo */
5338 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5339 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5340 /* sllv r_dstHi, r_srcHi, r_shift */
5341 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5342 r_dstHi
, r_srcHi
, MIPSRH_Reg(r_shift
)));
5343 /* or r_dstHi, a3, r_dstHi */
5344 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, a3
, MIPSRH_Reg(r_dstHi
)));
5345 /* andi a3, r_shift, 0x20 */
5346 addInstr(env
, MIPSInstr_Alu(Malu_AND
, a3
, r_shift
,
5347 MIPSRH_Imm(False
, 0x20)));
5348 /* sllv r_dstLo, r_srcLo, r_shift */
5349 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5350 r_dstLo
, r_srcLo
, MIPSRH_Reg(r_shift
)));
5351 #if (__mips_isa_rev >= 6)
5352 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, a3
));
5353 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_shift
, r_dstLo
, a3
));
5354 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, r_dstHi
, MIPSRH_Reg(r_shift
)));
5356 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, a3
));
5358 /* movn r_dstHi, r_dstLo, a3 */
5359 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, r_dstLo
, a3
));
5360 /* movn r_dstLo, zero, a3 */
5361 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, zero
, a3
));
5369 /* 64-bit arithmetic shift right based on what gcc generates:
5383 HReg r_srcHi
, r_srcLo
;
5384 HReg r_srcHitmp
= newVRegI(env
);
5385 HReg r_srcLotmp
= newVRegI(env
);
5386 HReg r_shift
= newVRegI(env
);
5387 HReg a3
= newVRegI(env
);
5388 HReg r_dstLo
= newVRegI(env
);
5389 HReg r_dstHi
= newVRegI(env
);
5390 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5393 iselInt64Expr(&r_srcLo
, &r_srcHi
, env
, e
->Iex
.Binop
.arg1
);
5394 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5396 if (sa
->tag
== Mrh_Imm
) {
5397 addInstr(env
, MIPSInstr_LI(r_shift
, sa
->Mrh
.Imm
.imm16
));
5400 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_shift
, sa
->Mrh
.Reg
.reg
,
5401 MIPSRH_Imm(False
, 0x3f)));
5403 /* nor r_dstLo, zero, r_shift */
5404 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(r_shift
)));
5405 /* sll a3, r_srcLo, 0x1 */
5406 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5407 a3
, r_srcLo
, MIPSRH_Imm(False
, 0x1)));
5408 /* sllv a3, a3, r_dstLo */
5409 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5410 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5411 /* srlv r_dstLo, r_srcHi, r_shift */
5412 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5413 r_dstLo
, r_srcHi
, MIPSRH_Reg(r_shift
)));
5414 /* srav r_dstHi, r_srcLo, r_shift */
5415 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
/* 32bit shift */,
5416 r_dstHi
, r_srcLo
, MIPSRH_Reg(r_shift
)));
5417 /* andi r_srcHi, r_shift, 0x20 */
5418 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcHitmp
, r_shift
,
5419 MIPSRH_Imm(False
, 0x20)));
5420 /* sra r_srcLo, r_srcLo, 0x1f */
5421 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
/* 32bit shift */,
5422 r_srcLotmp
, r_srcLo
, MIPSRH_Imm(False
, 0x1f)));
5423 /* or r_dstLo, a3, r_dstLo */
5424 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, a3
, MIPSRH_Reg(r_dstLo
)));
5425 #if (__mips_isa_rev >= 6)
5426 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, r_srcHitmp
));
5427 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_dstHi
, r_srcHitmp
));
5428 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, r_dstLo
, MIPSRH_Reg(a3
)));
5430 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, r_srcHitmp
));
5431 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_srcLotmp
, r_srcHitmp
));
5432 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, r_dstHi
, MIPSRH_Reg(a3
)));
5434 /* movn r_dstLo, r_dstHi, r_srcHi */
5435 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, r_dstHi
, r_srcHitmp
));
5436 /* movn r_dstHi, r_srcLo, r_srcHi */
5437 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, r_srcLotmp
, r_srcHitmp
));
5444 case Iop_F32toI64S
: {
5445 HReg tmpD
= newVRegD(env
);
5446 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
5447 HReg tLo
= newVRegI(env
);
5448 HReg tHi
= newVRegI(env
);
5451 /* CVTLS tmpD, valF */
5452 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
5453 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpD
, valF
));
5454 set_MIPS_rounding_default(env
);
5456 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5457 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5460 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
5463 #if defined (_MIPSEL)
5464 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5465 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5467 #elif defined (_MIPSEB)
5468 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5469 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5481 case Iop_F64toI64U
: {
5483 HReg tmp
= newVRegV(env
);
5485 r_src
= iselDblExpr( env
, e
->Iex
.Binop
.arg2
);
5486 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
5487 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_U
, MSA_F_DW
, tmp
, r_src
));
5488 HReg r_dsth
= newVRegI(env
);
5489 HReg r_dstl
= newVRegI(env
);
5491 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dstl
, MSA_DFN_W
| 0));
5493 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dsth
, MSA_DFN_W
| 1));
5496 set_MIPS_rounding_default_MSA(env
);
5500 case Iop_GetElem64x2
: {
5502 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
5503 HReg r_dstHI
= newVRegI(env
);
5504 HReg r_dstLO
= newVRegI(env
);
5505 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
5510 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dstHI
,
5512 (((tmp
->Mrh
.Imm
.imm16
& 0x01) << 1)
5515 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dstLO
,
5517 ((tmp
->Mrh
.Imm
.imm16
& 0x01) << 1)));
5521 HReg v_tmp
= newVRegV(env
);
5523 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_D
, v_tmp
, v_src
,
5526 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dstHI
,
5529 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dstLO
,
5541 HReg a_L
, a_H
, b_L
, b_H
;
5542 HReg dst_L
= newVRegI(env
);
5543 HReg dst_H
= newVRegI(env
);
5545 iselInt64Expr(&a_H
, &a_L
, env
, e
->Iex
.Binop
.arg1
);
5546 iselInt64Expr(&b_H
, &b_L
, env
, e
->Iex
.Binop
.arg2
);
5547 #if (__mips_isa_rev >= 6)
5548 addInstr(env
, MIPSInstr_Mulr6(True
, True
, True
,
5550 addInstr(env
, MIPSInstr_Mulr6(True
, True
, True
,
5552 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5553 MIPSRH_Reg(dst_L
)));
5554 addInstr(env
, MIPSInstr_Mulr6(False
, True
, False
,
5557 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5558 MIPSRH_Reg(dst_L
)));
5559 addInstr(env
, MIPSInstr_Mulr6(False
, True
, True
,
5562 addInstr(env
, MIPSInstr_Mul(dst_H
, a_H
, b_L
));
5563 addInstr(env
, MIPSInstr_Mult(True
, b_H
, a_L
));
5564 addInstr(env
, MIPSInstr_Mflo(dst_L
));
5565 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5566 MIPSRH_Reg(dst_L
)));
5567 addInstr(env
, MIPSInstr_Mult(False
, a_L
, b_L
));
5568 addInstr(env
, MIPSInstr_Mfhi(dst_L
));
5570 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5571 MIPSRH_Reg(dst_L
)));
5572 addInstr(env
, MIPSInstr_Mflo(dst_L
));
5580 HReg src1_L
, src1_H
, src2_L
, src2_H
;
5581 HReg dst_L
= newVRegI(env
);
5582 HReg dst_H
= newVRegI(env
);
5583 HReg tmp1
= newVRegV(env
);
5584 HReg tmp2
= newVRegV(env
);
5586 iselInt64Expr(&src1_H
, &src1_L
, env
, e
->Iex
.Binop
.arg1
);
5587 iselInt64Expr(&src2_H
, &src2_L
, env
, e
->Iex
.Binop
.arg2
);
5588 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src1_L
, tmp1
));
5589 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src1_H
, tmp1
, MSA_DFN_W
| 1));
5590 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src2_L
, tmp2
));
5591 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src2_H
, tmp2
, MSA_DFN_W
| 1));
5592 addInstr(env
, MIPSInstr_Msa3R(MSA_DIVS
, MSA_D
, tmp1
, tmp1
, tmp2
));
5593 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_H
, MSA_DFN_W
| 1));
5594 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_L
, MSA_DFN_W
| 0));
5601 HReg src1_L
, src1_H
, src2_L
, src2_H
;
5602 HReg dst_L
= newVRegI(env
);
5603 HReg dst_H
= newVRegI(env
);
5604 HReg tmp1
= newVRegV(env
);
5605 HReg tmp2
= newVRegV(env
);
5607 iselInt64Expr(&src1_H
, &src1_L
, env
, e
->Iex
.Binop
.arg1
);
5608 iselInt64Expr(&src2_H
, &src2_L
, env
, e
->Iex
.Binop
.arg2
);
5609 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src1_L
, tmp1
));
5610 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src1_H
, tmp1
, MSA_DFN_W
| 1));
5611 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src2_L
, tmp2
));
5612 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src2_H
, tmp2
, MSA_DFN_W
| 1));
5613 addInstr(env
, MIPSInstr_Msa3R(MSA_DIVU
, MSA_D
, tmp1
, tmp1
, tmp2
));
5614 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_H
, MSA_DFN_W
| 1));
5615 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_L
, MSA_DFN_W
| 0));
5621 case Iop_F64toI64S
: {
5622 HReg tmpD
= newVRegD(env
);
5624 HReg tLo
= newVRegI(env
);
5625 HReg tHi
= newVRegI(env
);
5629 valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
5631 valF
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
5634 /* CVTLS tmpD, valF */
5635 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
5636 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, tmpD
, valF
));
5637 set_MIPS_rounding_default(env
);
5639 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5640 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5643 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
5646 #if defined (_MIPSEL)
5647 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5648 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5650 #elif defined (_MIPSEB)
5651 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5652 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5670 /* --------- UNARY ops --------- */
5671 if (e
->tag
== Iex_Unop
) {
5672 switch (e
->Iex
.Unop
.op
) {
5674 HReg tLo
= newVRegI(env
);
5675 HReg tHi
= newVRegI(env
);
5676 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5677 HReg tmp
= newVRegI(env
);
5679 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, src
,
5680 MIPSRH_Imm(False
, 31)));
5681 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tmp
, tmp
,
5682 MIPSRH_Imm(False
, 31)));
5684 addInstr(env
, mk_iMOVds_RR(tHi
, tmp
));
5685 addInstr(env
, mk_iMOVds_RR(tLo
, tmp
));
5694 HReg tLo
= newVRegI(env
);
5695 HReg tHi
= newVRegI(env
);
5696 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5697 UInt no_bits
= (e
->Iex
.Unop
.op
== Iop_8Sto64
) ? 24 : 16;
5698 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5699 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tLo
, tLo
,
5700 MIPSRH_Imm(False
, no_bits
)));
5701 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tHi
, tLo
,
5702 MIPSRH_Imm(False
, 31)));
5703 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tLo
, tLo
,
5704 MIPSRH_Imm(False
, no_bits
)));
5705 addInstr(env
, mk_iMOVds_RR(tHi
, tLo
));
5713 HReg tLo
= newVRegI(env
);
5714 HReg tHi
= newVRegI(env
);
5715 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5716 addInstr(env
, mk_iMOVds_RR(tHi
, src
));
5717 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5718 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tHi
, tHi
,
5719 MIPSRH_Imm(False
, 31)));
5727 HReg tLo
= newVRegI(env
);
5728 HReg tHi
= newVRegI(env
);
5729 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5730 UInt mask
= (e
->Iex
.Unop
.op
== Iop_8Sto64
) ? 0xFF : 0xFFFF;
5731 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo
, src
,
5732 MIPSRH_Imm(False
, mask
)));
5733 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, hregMIPS_GPR0(mode64
),
5734 MIPSRH_Reg(hregMIPS_GPR0(mode64
))));
5742 HReg tLo
= newVRegI(env
);
5743 HReg tHi
= newVRegI(env
);
5744 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5745 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5746 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, hregMIPS_GPR0(mode64
),
5747 MIPSRH_Reg(hregMIPS_GPR0(mode64
))));
5755 HReg tHi
= newVRegI(env
);
5756 HReg tLo
= newVRegI(env
);
5757 HReg tmp
= newVRegI(env
);
5758 HReg tmp1
= newVRegI(env
);
5759 HReg tmp2
= newVRegI(env
);
5760 HReg zero
= newVRegI(env
);
5761 MIPSCondCode cc
= MIPScc_LO
;
5764 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Unop
.arg
);
5766 addInstr(env
, MIPSInstr_LI(zero
, 0x00000000));
5768 /* tmp2:tmp1 = 0 - (yHi:yLo)*/
5769 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp2
, zero
, MIPSRH_Reg(yLo
)));
5770 addInstr(env
, MIPSInstr_Cmp(False
, True
, tmp1
, zero
, tmp2
, cc
));
5771 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp
, zero
, MIPSRH_Reg(yHi
)));
5772 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp1
, tmp
, MIPSRH_Reg(tmp1
)));
5774 /* So now we have tmp2:tmp1 = -arg. To finish off, or 'arg'
5775 back in, so as to give the final result
5776 tHi:tLo = arg | -arg. */
5777 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tHi
, yHi
, MIPSRH_Reg(tmp1
)));
5778 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tLo
, yLo
, MIPSRH_Reg(tmp2
)));
5784 case Iop_CmpwNEZ64
: {
5786 HReg tmp1
= newVRegI(env
);
5787 HReg tmp2
= newVRegI(env
);
5788 /* srcHi:srcLo = arg */
5789 iselInt64Expr(&srcHi
, &srcLo
, env
, e
->Iex
.Unop
.arg
);
5790 /* tmp1 = srcHi | srcLo */
5791 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp1
, srcLo
,
5792 MIPSRH_Reg(srcHi
)));
5793 /* tmp2 = (tmp1 | -tmp1) >>s 31 */
5795 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp2
, hregMIPS_GPR0(mode64
),
5798 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp2
, tmp2
, MIPSRH_Reg(tmp1
)));
5799 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tmp2
, tmp2
,
5800 MIPSRH_Imm(False
, 31)));
5806 case Iop_ReinterpF64asI64
: {
5807 HReg tLo
= newVRegI(env
);
5808 HReg tHi
= newVRegI(env
);
5810 HReg fr_src
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
5812 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5813 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5816 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
5819 #if defined (_MIPSEL)
5820 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5821 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5823 #elif defined (_MIPSEB)
5824 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5825 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5838 HReg tLo
= newVRegI(env
);
5839 HReg tHi
= newVRegI(env
);
5840 iselInt64Expr(&tHi
, &tLo
, env
, e
->Iex
.Unop
.arg
);
5841 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tLo
, tLo
, MIPSRH_Reg(tLo
)));
5842 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tHi
, tHi
, MIPSRH_Reg(tHi
)));
5849 case Iop_V128HIto64
: {
5851 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5852 HReg tLo
= newVRegI(env
);
5853 HReg tHi
= newVRegI(env
);
5854 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 2));
5855 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 3));
5861 case Iop_V128to64
: {
5863 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5864 HReg tLo
= newVRegI(env
);
5865 HReg tHi
= newVRegI(env
);
5866 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 0));
5867 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 1));
5873 case Iop_F32toF16x4_DEP
: {
5875 HReg v_arg
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5876 HReg v_src
= newVRegV(env
);
5877 set_guest_MIPS_rounding_mode_MSA(env
);
5878 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXDO
, MSA_F_WH
, v_src
, v_arg
, v_arg
));
5879 set_MIPS_rounding_default_MSA(env
);
5880 HReg tLo
= newVRegI(env
);
5881 HReg tHi
= newVRegI(env
);
5882 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 0));
5883 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 1));
5890 vex_printf("UNARY: No such op: ");
5891 ppIROp(e
->Iex
.Unop
.op
);
5897 vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e
->tag
);
5899 vpanic("iselInt64Expr(mips)");
5902 /*---------------------------------------------------------*/
5903 /*--- ISEL: Floating point expressions (32 bit) ---*/
5904 /*---------------------------------------------------------*/
5906 /* Nothing interesting here; really just wrappers for
5908 static HReg
iselFltExpr(ISelEnv
* env
, IRExpr
* e
)
5911 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
5912 if (ty
== Ity_F32
|| (ty
== Ity_F64
&& fp_mode64
)) {
5913 r
= iselFltExpr_wrk(env
, e
);
5915 r
= iselDblExpr_wrk(env
, e
);
5916 vassert(hregClass(r
) == HRcFlt64
);
5921 /* DO NOT CALL THIS DIRECTLY */
5922 static HReg
iselFltExpr_wrk(ISelEnv
* env
, IRExpr
* e
)
5924 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
5925 vassert(ty
== Ity_F32
|| (ty
== Ity_F64
&& fp_mode64
));
5927 if (e
->tag
== Iex_RdTmp
) {
5928 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
5931 if (e
->tag
== Iex_Load
) {
5932 vassert(e
->Iex
.Load
.ty
== Ity_F32
5933 || (e
->Iex
.Load
.ty
== Ity_F64
&& fp_mode64
));
5935 MIPSAMode
*am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
5936 if (e
->Iex
.Load
.ty
== Ity_F64
) {
5937 r_dst
= newVRegD(env
);
5938 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
5940 r_dst
= newVRegF(env
);
5941 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 4, r_dst
, am_addr
));
5946 if (e
->tag
== Iex_Get
) {
5947 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
5948 GuestStatePointer(mode64
));
5950 if (e
->Iex
.Load
.ty
== Ity_F64
) {
5951 r_dst
= newVRegD(env
);
5952 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
5954 r_dst
= newVRegF(env
);
5955 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 4, r_dst
, am_addr
));
5960 if (e
->tag
== Iex_Unop
) {
5961 switch (e
->Iex
.Unop
.op
) {
5962 case Iop_ReinterpI32asF32
: {
5963 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5964 HReg r_dst
= newVRegF(env
);
5966 /* Move Word to Floating Point
5968 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, fr_src
));
5972 case Iop_F32toF64
: {
5974 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5975 HReg dst
= newVRegD(env
);
5977 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDS
, dst
, src
));
5980 case Iop_ReinterpI64asF64
: {
5983 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5984 r_dst
= newVRegF(env
);
5985 /* Move Doubleword to Floating Point
5986 dmtc1 r_dst, fr_src */
5987 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmtc1
, r_dst
, fr_src
));
5990 r_dst
= newVRegD(env
);
5991 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Unop
.arg
);
5992 r_dst
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
5996 case Iop_I32StoF64
: {
5998 HReg dst
= newVRegF(env
);
5999 HReg tmp
= newVRegF(env
);
6000 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
6002 /* Move Word to Floating Point
6004 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, r_src
));
6006 /* and do convert */
6007 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDW
, dst
, tmp
));
6013 Bool sz32
= e
->Iex
.Unop
.op
== Iop_AbsF32
;
6014 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6015 HReg dst
= newVRegF(env
);
6016 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_ABSS
: Mfp_ABSD
, dst
, src
));
6021 Bool sz32
= e
->Iex
.Unop
.op
== Iop_NegF32
;
6022 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6023 HReg dst
= newVRegF(env
);
6024 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_NEGS
: Mfp_NEGD
, dst
, src
));
6027 case Iop_RoundF64toF64_ZERO
: {
6029 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6030 HReg dst
= newVRegF(env
);
6031 addInstr(env
, MIPSInstr_FpConvert(Mfp_TRULD
, dst
, src
));
6034 case Iop_RoundF64toF64_NEAREST
: {
6036 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6037 HReg dst
= newVRegF(env
);
6038 addInstr(env
, MIPSInstr_FpConvert(Mfp_ROUNDLD
, dst
, src
));
6041 case Iop_RoundF64toF64_NegINF
: {
6043 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6044 HReg dst
= newVRegF(env
);
6045 addInstr(env
, MIPSInstr_FpConvert(Mfp_FLOORLD
, dst
, src
));
6048 case Iop_RoundF64toF64_PosINF
: {
6050 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6051 HReg dst
= newVRegF(env
);
6052 addInstr(env
, MIPSInstr_FpConvert(Mfp_CEILLD
, dst
, src
));
6061 if (e
->tag
== Iex_Triop
) {
6062 switch (e
->Iex
.Triop
.details
->op
) {
6072 HReg argL
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6073 HReg argR
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6074 HReg dst
= newVRegF(env
);
6075 switch (e
->Iex
.Triop
.details
->op
) {
6107 set_MIPS_rounding_mode(env
, e
->Iex
.Triop
.details
->arg1
);
6108 addInstr(env
, MIPSInstr_FpBinary(op
, dst
, argL
, argR
));
6109 set_MIPS_rounding_default(env
);
6112 case Iop_ScaleF64
: {
6113 HReg src1
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6114 HReg src2
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6115 HReg v_help
= newVRegV(env
);
6116 HReg dst
= newVRegF(env
);
6118 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
6119 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_S
, MSA_F_DW
, v_help
, src2
));
6120 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
, dst
, src1
, v_help
));
6121 set_MIPS_rounding_default_MSA(env
);
6130 if (e
->tag
== Iex_Binop
) {
6131 switch (e
->Iex
.Binop
.op
) {
6132 case Iop_F64toF32
: {
6135 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6137 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6138 HReg valS
= newVRegF(env
);
6140 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6141 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSD
, valS
, valD
));
6142 set_MIPS_rounding_default(env
);
6146 case Iop_RoundF32toInt
: {
6147 HReg valS
= newVRegF(env
);
6148 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6150 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6151 #if (__mips_isa_rev >= 6)
6152 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTS
, valS
, valF
));
6154 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWS
, valS
, valF
));
6155 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSW
, valS
, valS
));
6157 set_MIPS_rounding_default(env
);
6161 case Iop_RoundF64toInt
: {
6162 HReg valS
= newVRegF(env
);
6163 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6165 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6166 #if (__mips_isa_rev >= 6)
6167 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTD
, valS
, valF
));
6169 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, valS
, valF
));
6170 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, valS
, valS
));
6173 set_MIPS_rounding_default(env
);
6177 case Iop_I32StoF32
: {
6178 HReg r_dst
= newVRegF(env
);
6179 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6180 HReg tmp
= newVRegF(env
);
6182 /* Move Word to Floating Point
6184 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, fr_src
));
6186 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6187 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSW
, r_dst
, tmp
));
6188 set_MIPS_rounding_default(env
);
6193 case Iop_I64StoF64
: {
6194 HReg r_dst
= newVRegF(env
);
6198 tmp
= newVRegF(env
);
6199 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6200 /* Move SP down 8 bytes */
6201 sub_from_sp(env
, 8);
6202 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6205 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6207 /* load as Ity_F64 */
6208 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6214 tmp
= newVRegD(env
);
6215 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6216 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6219 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6220 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6221 set_MIPS_rounding_default(env
);
6226 case Iop_I64StoF32
: {
6227 HReg r_dst
= newVRegF(env
);
6231 tmp
= newVRegF(env
);
6232 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6233 /* Move SP down 8 bytes */
6234 sub_from_sp(env
, 8);
6235 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6238 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6240 /* load as Ity_F64 */
6241 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6247 tmp
= newVRegD(env
);
6248 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6249 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6252 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6253 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSL
, r_dst
, tmp
));
6254 set_MIPS_rounding_default(env
);
6261 Bool sz32
= e
->Iex
.Binop
.op
== Iop_SqrtF32
;
6262 HReg src
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6263 HReg dst
= newVRegF(env
);
6264 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6265 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_SQRTS
: Mfp_SQRTD
, dst
,
6267 set_MIPS_rounding_default(env
);
6271 case Iop_I64UtoF64
: {
6273 HReg r_dst
= newVRegF(env
);
6274 HReg tmp
= newVRegV(env
);
6277 r_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6278 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
6279 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src
, tmp
));
6280 HReg r_srch
= newVRegI(env
);
6281 addInstr(env
, MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_DW
, tmp
, tmp
));
6282 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srch
, MSA_DFN_D
| 0));
6283 sub_from_sp(env
, 8);
6284 MIPSAMode
*am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6287 addInstr(env
, MIPSInstr_Store(8, am_addr
, r_srch
, mode64
));
6289 /* load as Ity_F64 */
6290 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
6294 set_MIPS_rounding_default_MSA(env
);
6298 #if (__mips_isa_rev >= 6)
6299 case Iop_MaxNumF32
: {
6300 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6301 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6302 HReg dst
= newVRegF(env
);
6303 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXS
, dst
,
6308 case Iop_MaxNumF64
: {
6309 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6310 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6311 HReg dst
= newVRegF(env
);
6312 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXD
, dst
,
6317 case Iop_MinNumF32
: {
6318 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6319 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6320 HReg dst
= newVRegF(env
);
6321 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MINS
, dst
,
6326 case Iop_MinNumF64
: {
6327 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6328 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6329 HReg dst
= newVRegF(env
);
6330 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MIND
, dst
,
6340 if (e
->tag
== Iex_Qop
) {
6341 switch (e
->Iex
.Qop
.details
->op
) {
6347 #if (__mips_isa_rev < 6)
6350 switch (e
->Iex
.Qop
.details
->op
) {
6351 #if (__mips_isa_rev >= 6)
6366 op
= has_msa
? MSA_FMADD
: Mfp_MADDS
;
6370 op
= has_msa
? MSA_FMADD
: Mfp_MADDD
;
6374 op
= has_msa
? MSA_FMSUB
: Mfp_MSUBS
;
6378 op
= has_msa
? MSA_FMSUB
: Mfp_MSUBD
;
6386 HReg dst
= newVRegF(env
);
6387 HReg src1
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg2
);
6388 HReg src2
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg3
);
6389 HReg src3
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg4
);
6390 #if (__mips_isa_rev >= 6)
6391 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6392 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6394 set_MIPS_rounding_default(env
);
6397 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, src3
, dst
, 0));
6398 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Qop
.details
->arg1
);
6399 addInstr(env
, MIPSInstr_Msa3RF(op
, type
, dst
, src1
, src2
));
6400 set_MIPS_rounding_default_MSA(env
);
6402 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6403 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6405 set_MIPS_rounding_default(env
);
6416 if (e
->tag
== Iex_Unop
&& e
->Iex
.Unop
.op
== Iop_TruncF64asF32
) {
6417 /* This is quite subtle. The only way to do the relevant
6418 truncation is to do a single-precision store and then a
6419 double precision load to get it back into a register. The
6420 problem is, if the data is then written to memory a second
6423 STbe(...) = TruncF64asF32(...)
6425 then will the second truncation further alter the value? The
6426 answer is no: flds (as generated here) followed by fsts
6427 (generated for the STbe) is the identity function on 32-bit
6428 floats, so we are safe.
6430 Another upshot of this is that if iselStmt can see the
6433 STbe(...) = TruncF64asF32(arg)
6435 then it can short circuit having to deal with TruncF64asF32
6436 individually; instead just compute arg into a 64-bit FP
6437 register and do 'fsts' (since that itself does the
6440 We generate pretty poor code here (should be ok both for
6441 32-bit and 64-bit mode); but it is expected that for the most
6442 part the latter optimisation will apply and hence this code
6443 will not often be used.
6445 HReg fsrc
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
6446 HReg fdst
= newVRegF(env
);
6447 MIPSAMode
*zero_r1
= MIPSAMode_IR(0, StackPointer(mode64
));
6449 sub_from_sp(env
, 16);
6450 /* store as F32, hence truncating */
6451 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fsrc
, zero_r1
));
6452 /* and reload. Good huh?! (sigh) */
6453 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 4, fdst
, zero_r1
));
6458 /* --------- ITE --------- */
6459 if (e
->tag
== Iex_ITE
) {
6460 vassert(typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
);
6461 HReg r0
= iselFltExpr(env
, e
->Iex
.ITE
.iffalse
);
6462 HReg r1
= iselFltExpr(env
, e
->Iex
.ITE
.iftrue
);
6463 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
6464 HReg r_dst
= newVRegF(env
);
6465 #if (__mips_isa_rev >= 6)
6466 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, r_cond
));
6467 addInstr(env
, MIPSInstr_MoveCond(MFpSeld
, r_dst
, r0
, r1
));
6469 addInstr(env
, MIPSInstr_FpUnary((ty
== Ity_F64
) ? Mfp_MOVD
: Mfp_MOVS
,
6471 addInstr(env
, MIPSInstr_MoveCond((ty
== Ity_F64
) ? MFpMoveCond_movnd
:
6473 r_dst
, r1
, r_cond
));
6478 vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e
->tag
);
6480 vpanic("iselFltExpr_wrk(mips)");
6483 static HReg
iselDblExpr(ISelEnv
* env
, IRExpr
* e
)
6485 HReg r
= iselDblExpr_wrk(env
, e
);
6486 vassert(hregClass(r
) == HRcFlt64
);
6487 vassert(hregIsVirtual(r
));
6491 /* DO NOT CALL THIS DIRECTLY */
6492 static HReg
iselDblExpr_wrk(ISelEnv
* env
, IRExpr
* e
)
6494 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
6496 vassert(ty
== Ity_F64
);
6498 if (e
->tag
== Iex_RdTmp
) {
6499 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
6502 /* --------- LOAD --------- */
6503 if (e
->tag
== Iex_Load
) {
6504 HReg r_dst
= newVRegD(env
);
6506 vassert(e
->Iex
.Load
.ty
== Ity_F64
);
6507 am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
6508 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, r_dst
, am_addr
));
6512 /* --------- GET --------- */
6513 if (e
->tag
== Iex_Get
) {
6515 HReg r_dst
= newVRegD(env
);
6516 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
6517 GuestStatePointer(mode64
));
6518 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, r_dst
, am_addr
));
6522 if (e
->tag
== Iex_Unop
) {
6523 MIPSFpOp fpop
= Mfp_INVALID
;
6524 switch (e
->Iex
.Unop
.op
) {
6531 case Iop_F32toF64
: {
6533 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6534 HReg dst
= newVRegD(env
);
6536 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDS
, dst
, src
));
6539 case Iop_ReinterpI64asF64
: {
6541 HReg dst
= newVRegD(env
);
6543 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Unop
.arg
);
6545 dst
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6548 case Iop_I32StoF64
: {
6550 HReg dst
= newVRegD(env
);
6551 HReg tmp
= newVRegF(env
);
6552 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
6554 /* Move Word to Floating Point
6556 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, r_src
));
6558 /* and do convert */
6559 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDW
, dst
, tmp
));
6567 if (fpop
!= Mfp_INVALID
) {
6568 HReg src
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
6569 HReg dst
= newVRegD(env
);
6570 addInstr(env
, MIPSInstr_FpUnary(fpop
, dst
, src
));
6575 if (e
->tag
== Iex_Binop
) {
6576 switch (e
->Iex
.Binop
.op
) {
6577 case Iop_RoundF64toInt
: {
6578 HReg src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6579 HReg dst
= newVRegD(env
);
6581 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6582 #if (__mips_isa_rev >= 6)
6583 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTD
, dst
, src
));
6585 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, dst
, src
));
6586 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, dst
, dst
));
6589 set_MIPS_rounding_default(env
);
6595 HReg src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6596 HReg dst
= newVRegD(env
);
6597 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6598 addInstr(env
, MIPSInstr_FpUnary(Mfp_SQRTD
, dst
, src
));
6599 set_MIPS_rounding_default(env
);
6603 case Iop_I64StoF64
: {
6604 HReg r_dst
= newVRegD(env
);
6608 tmp
= newVRegD(env
);
6609 fr_src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6610 /* Move SP down 8 bytes */
6611 sub_from_sp(env
, 8);
6612 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6615 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6617 /* load as Ity_F64 */
6618 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6624 tmp
= newVRegD(env
);
6625 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6626 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6629 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6630 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6631 set_MIPS_rounding_default(env
);
6636 case Iop_I64UtoF64
: {
6638 HReg tmp
= newVRegV(env
);
6639 HReg r_src2h
, r_src2l
;
6641 iselInt64Expr(&r_src2h
, &r_src2l
, env
, e
->Iex
.Binop
.arg2
);
6642 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
6643 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_src2l
, tmp
));
6644 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, tmp
, MSA_DFN_W
| 1));
6645 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2l
, tmp
, MSA_DFN_W
| 2));
6646 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, tmp
, MSA_DFN_W
| 3));
6647 HReg r_srchh
= newVRegI(env
);
6648 HReg r_srchl
= newVRegI(env
);
6649 addInstr(env
, MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_DW
, tmp
, tmp
));
6650 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srchl
, MSA_DFN_W
| 0));
6651 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srchh
, MSA_DFN_W
| 1));
6652 r_dst
= mk_LoadRR32toFPR(env
, r_srchh
, r_srchl
);
6653 set_MIPS_rounding_default_MSA(env
);
6656 #if (__mips_isa_rev >= 6)
6657 case Iop_MaxNumF64
: {
6658 HReg src1
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
6659 HReg src2
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6660 HReg dst
= newVRegD(env
);
6661 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXD
, dst
,
6666 case Iop_MinNumF64
: {
6667 HReg src1
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
6668 HReg src2
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6669 HReg dst
= newVRegD(env
);
6670 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MIND
, dst
,
6682 if (e
->tag
== Iex_Triop
) {
6683 switch (e
->Iex
.Triop
.details
->op
) {
6690 HReg argL
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6691 HReg argR
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6692 HReg dst
= newVRegD(env
);
6693 switch (e
->Iex
.Triop
.details
->op
) {
6712 set_MIPS_rounding_mode(env
, e
->Iex
.Triop
.details
->arg1
);
6713 addInstr(env
, MIPSInstr_FpBinary(op
, dst
, argL
, argR
));
6714 set_MIPS_rounding_default(env
);
6718 case Iop_ScaleF64
: {
6719 HReg src1
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6720 HReg src2
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6721 HReg v_help
= newVRegV(env
);
6722 HReg dst
= newVRegD(env
);
6724 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
6725 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_S
, MSA_F_DW
, v_help
, src2
));
6726 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
, dst
, src1
, v_help
));
6727 set_MIPS_rounding_default_MSA(env
);
6735 if (e
->tag
== Iex_Qop
) {
6736 switch (e
->Iex
.Qop
.details
->op
) {
6740 switch (e
->Iex
.Qop
.details
->op
) {
6741 #if (__mips_isa_rev >= 6)
6759 HReg dst
= newVRegD(env
);
6760 HReg src1
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg2
);
6761 HReg src2
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg3
);
6762 HReg src3
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg4
);
6763 #if (__mips_isa_rev >= 6)
6764 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6765 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6767 set_MIPS_rounding_default(env
);
6770 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, src3
, dst
, 0));
6771 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Qop
.details
->arg1
);
6772 addInstr(env
, MIPSInstr_Msa3RF(op
, MSA_F_DW
, dst
, src1
, src2
));
6773 set_MIPS_rounding_default_MSA(env
);
6777 case Iop_I64StoF64
: {
6778 HReg r_dst
= newVRegD(env
);
6782 tmp
= newVRegF(env
);
6783 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6784 /* Move SP down 8 bytes */
6785 sub_from_sp(env
, 8);
6786 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6789 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6791 /* load as Ity_F64 */
6792 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6798 tmp
= newVRegD(env
);
6799 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6800 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6803 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6804 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6805 set_MIPS_rounding_default(env
);
6815 /* --------- ITE --------- */
6816 if (e
->tag
== Iex_ITE
) {
6818 && typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
) {
6819 HReg r0
= iselDblExpr(env
, e
->Iex
.ITE
.iffalse
);
6820 HReg r1
= iselDblExpr(env
, e
->Iex
.ITE
.iftrue
);
6821 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
6822 HReg r_dst
= newVRegD(env
);
6823 #if (__mips_isa_rev >= 6)
6824 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, r_cond
));
6825 addInstr(env
, MIPSInstr_MoveCond(MFpSeld
, r_dst
, r0
, r1
));
6827 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, r_dst
, r0
));
6828 addInstr(env
, MIPSInstr_MoveCond(MFpMoveCond_movnd
, r_dst
, r1
,
6835 vex_printf("iselDblExpr(mips): No such tag(%u)\n", e
->tag
);
6837 vpanic("iselDblExpr_wrk(mips)");
6840 /*---------------------------------------------------------*/
6841 /*--- ISEL: Statements ---*/
6842 /*---------------------------------------------------------*/
6844 static void iselStmt(ISelEnv
* env
, IRStmt
* stmt
)
6846 if (vex_traceflags
& VEX_TRACE_VCODE
) {
6847 vex_printf("\n-- ");
6853 switch (stmt
->tag
) {
6854 /* --------- STORE --------- */
6857 IRType tyd
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.Store
.data
);
6859 if (tyd
== Ity_V128
) {
6861 HReg res
= iselV128Expr(env
, stmt
->Ist
.Store
.data
);
6862 HReg addr
= iselWordExpr_R(env
, stmt
->Ist
.Store
.addr
);
6863 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, 0, addr
, res
, MSA_B
));
6867 /*constructs addressing mode from address provided */
6868 am_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.Store
.addr
, tyd
);
6870 if (tyd
== Ity_I8
|| tyd
== Ity_I16
|| tyd
== Ity_I32
||
6871 (mode64
&& (tyd
== Ity_I64
))) {
6872 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.Store
.data
);
6873 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(tyd
)),
6874 am_addr
, r_src
, mode64
));
6877 if (!mode64
&& (tyd
== Ity_I64
)) {
6879 HReg r_addr
= iselWordExpr_R(env
, stmt
->Ist
.Store
.addr
);
6881 iselInt64Expr(&vHi
, &vLo
, env
, stmt
->Ist
.Store
.data
);
6883 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6884 MIPSAMode_IR(0, r_addr
), vHi
, mode64
));
6885 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6886 MIPSAMode_IR(4, r_addr
), vLo
, mode64
));
6889 if (tyd
== Ity_F32
) {
6890 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Store
.data
);
6891 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fr_src
,
6895 if (tyd
== Ity_F64
&& mode64
) {
6896 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Store
.data
);
6897 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6901 if (!mode64
&& (tyd
== Ity_F64
)) {
6902 HReg fr_src
= iselDblExpr(env
, stmt
->Ist
.Store
.data
);
6903 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6911 /* --------- PUT --------- */
6913 IRType ty
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.Put
.data
);
6915 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
||
6916 (ty
== Ity_I64
&& mode64
)) {
6917 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.Put
.data
);
6918 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6919 GuestStatePointer(mode64
));
6920 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(ty
)),
6921 am_addr
, r_src
, mode64
));
6925 if (ty
== Ity_I64
&& !mode64
) {
6927 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6928 GuestStatePointer(mode64
));
6929 MIPSAMode
*am_addr4
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
+ 4,
6930 GuestStatePointer(mode64
));
6931 iselInt64Expr(&vHi
, &vLo
, env
, stmt
->Ist
.Put
.data
);
6932 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6933 am_addr
, vLo
, mode64
));
6934 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6935 am_addr4
, vHi
, mode64
));
6940 if (ty
== Ity_F32
) {
6941 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Put
.data
);
6942 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6943 GuestStatePointer(mode64
));
6944 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fr_src
,
6949 if (ty
== Ity_F64
) {
6951 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Put
.data
);
6952 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6953 GuestStatePointer(mode64
));
6954 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6957 HReg fr_src
= iselDblExpr(env
, stmt
->Ist
.Put
.data
);
6958 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6959 GuestStatePointer(mode64
));
6960 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6965 if (ty
== Ity_V128
) {
6967 HReg v_src
= iselV128Expr(env
, stmt
->Ist
.Put
.data
);
6968 #if defined(_MIPSEB)
6969 vassert(!(stmt
->Ist
.Put
.offset
& ~0x7FFF));
6970 HReg r_addr
= newVRegI(env
);
6971 addInstr(env
, MIPSInstr_Alu(mode64
? Malu_DADD
: Malu_ADD
, r_addr
, GuestStatePointer(mode64
),
6972 MIPSRH_Imm(True
, stmt
->Ist
.Put
.offset
)));
6973 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, 0, r_addr
, v_src
, MSA_B
));
6975 vassert(!(stmt
->Ist
.Put
.offset
& 7));
6976 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, stmt
->Ist
.Put
.offset
>> 3,
6977 GuestStatePointer(mode64
), v_src
, MSA_D
));
6984 /* --------- TMP --------- */
6986 IRTemp tmp
= stmt
->Ist
.WrTmp
.tmp
;
6987 IRType ty
= typeOfIRTemp(env
->type_env
, tmp
);
6989 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
|| ty
== Ity_I1
) {
6990 HReg r_dst
= lookupIRTemp(env
, tmp
);
6991 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.WrTmp
.data
);
6992 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
6996 if (ty
== Ity_I64
) {
6998 HReg r_dst
= lookupIRTemp(env
, tmp
);
6999 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.WrTmp
.data
);
7000 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
7003 HReg rHi
, rLo
, dstHi
, dstLo
;
7004 iselInt64Expr(&rHi
, &rLo
, env
, stmt
->Ist
.WrTmp
.data
);
7005 lookupIRTemp64(&dstHi
, &dstLo
, env
, tmp
);
7006 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
7007 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
7012 if (mode64
&& ty
== Ity_I128
) {
7013 HReg rHi
, rLo
, dstHi
, dstLo
;
7014 iselInt128Expr(&rHi
, &rLo
, env
, stmt
->Ist
.WrTmp
.data
);
7015 lookupIRTempPair(&dstHi
, &dstLo
, env
, tmp
);
7016 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
7017 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
7021 if (ty
== Ity_F32
) {
7022 HReg fr_dst
= lookupIRTemp(env
, tmp
);
7023 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.WrTmp
.data
);
7024 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVS
, fr_dst
, fr_src
));
7028 if (ty
== Ity_F64
) {
7030 HReg src
= iselFltExpr(env
, stmt
->Ist
.WrTmp
.data
);
7031 HReg dst
= lookupIRTemp(env
, tmp
);
7032 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, dst
, src
));
7035 HReg src
= iselDblExpr(env
, stmt
->Ist
.WrTmp
.data
);
7036 HReg dst
= lookupIRTemp(env
, tmp
);
7037 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, dst
, src
));
7042 if (ty
== Ity_V128
) {
7044 HReg v_dst
= lookupIRTemp(env
, tmp
);
7045 HReg v_src
= iselV128Expr(env
, stmt
->Ist
.WrTmp
.data
);
7046 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, v_src
, v_dst
, 0));
7052 /* --------- Call to DIRTY helper --------- */
7054 IRDirty
*d
= stmt
->Ist
.Dirty
.details
;
7056 /* Figure out the return type, if any. */
7057 IRType retty
= Ity_INVALID
;
7058 if (d
->tmp
!= IRTemp_INVALID
)
7059 retty
= typeOfIRTemp(env
->type_env
, d
->tmp
);
7061 /* Throw out any return types we don't know about. */
7062 Bool retty_ok
= False
;
7064 case Ity_INVALID
: /* Function doesn't return anything. */
7066 case Ity_I64
: case Ity_I32
: case Ity_I16
: case Ity_I8
:
7067 retty_ok
= True
; break;
7073 break; /* will go to stmt_fail: */
7075 /* Marshal args, do the call, clear stack, set the return value
7076 to 0x555..555 if this is a conditional call that returns a
7077 value and the call is skipped. */
7079 RetLoc rloc
= mk_RetLoc_INVALID();
7080 doHelperCall( &addToSp
, &rloc
, env
, d
->guard
, d
->cee
, retty
, d
->args
);
7081 vassert(is_sane_RetLoc(rloc
));
7083 /* Now figure out what to do with the returned value, if any. */
7086 /* No return value. Nothing to do. */
7087 vassert(d
->tmp
== IRTemp_INVALID
);
7088 vassert(rloc
.pri
== RLPri_None
);
7089 vassert(addToSp
== 0);
7092 case Ity_I32
: case Ity_I16
: case Ity_I8
: {
7093 /* The returned value is in $v0. Park it in the register
7094 associated with tmp. */
7095 HReg r_dst
= lookupIRTemp(env
, d
->tmp
);
7096 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_dst
,
7097 hregMIPS_GPR2(mode64
),
7098 MIPSRH_Imm(False
, 0)));
7099 vassert(rloc
.pri
== RLPri_Int
);
7100 vassert(addToSp
== 0);
7105 /* The returned value is in $v0. Park it in the register
7106 associated with tmp. */
7107 HReg r_dst
= lookupIRTemp(env
, d
->tmp
);
7108 addInstr(env
, mk_iMOVds_RR(r_dst
, hregMIPS_GPR2(mode64
)));
7109 vassert(rloc
.pri
== RLPri_Int
);
7110 vassert(addToSp
== 0);
7113 HReg rHi
= newVRegI(env
);
7114 HReg rLo
= newVRegI(env
);
7116 addInstr(env
, mk_iMOVds_RR(rLo
, hregMIPS_GPR2(mode64
)));
7117 addInstr(env
, mk_iMOVds_RR(rHi
, hregMIPS_GPR3(mode64
)));
7118 lookupIRTemp64(&dstHi
, &dstLo
, env
, d
->tmp
);
7119 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
7120 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
7126 vassert(rloc
.pri
== RLPri_V128SpRel
);
7127 vassert((rloc
.spOff
< 512) && (rloc
.spOff
> -512));
7128 vassert(addToSp
>= 16);
7129 HReg dst
= lookupIRTemp(env
, d
->tmp
);
7130 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, rloc
.spOff
, StackPointer(mode64
), dst
, MSA_B
));
7131 add_to_sp(env
, addToSp
);
7141 /* --------- Load Linked or Store Conditional --------- */
7143 /* Temporary solution; this need to be rewritten again for MIPS.
7144 On MIPS you can not read from address that is locked with LL
7145 before SC. If you read from address that is locked than SC will
7147 IRTemp res
= stmt
->Ist
.LLSC
.result
;
7148 IRType tyRes
= typeOfIRTemp(env
->type_env
, res
);
7149 IRType tyAddr
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.LLSC
.addr
);
7151 if (!mode64
&& (tyAddr
!= Ity_I32
))
7154 if (stmt
->Ist
.LLSC
.storedata
== NULL
) {
7157 /* constructs addressing mode from address provided */
7158 r_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.LLSC
.addr
, tyAddr
);
7160 HReg r_dst
= lookupIRTemp(env
, res
);
7161 if (tyRes
== Ity_I32
) {
7162 addInstr(env
, MIPSInstr_LoadL(4, r_dst
, r_addr
, mode64
));
7164 } else if (tyRes
== Ity_I64
&& mode64
) {
7165 addInstr(env
, MIPSInstr_LoadL(8, r_dst
, r_addr
, mode64
));
7171 r_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.LLSC
.addr
, tyAddr
);
7172 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.LLSC
.storedata
);
7173 HReg r_dst
= lookupIRTemp(env
, res
);
7174 IRType tyData
= typeOfIRExpr(env
->type_env
,
7175 stmt
->Ist
.LLSC
.storedata
);
7177 if (tyData
== Ity_I32
) {
7178 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
7179 addInstr(env
, MIPSInstr_StoreC(4, r_addr
, r_dst
, mode64
));
7181 } else if (tyData
== Ity_I64
&& mode64
) {
7182 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
7183 addInstr(env
, MIPSInstr_StoreC(8, r_addr
, r_dst
, mode64
));
7191 if (stmt
->Ist
.CAS
.details
->oldHi
== IRTemp_INVALID
) {
7192 IRCAS
*cas
= stmt
->Ist
.CAS
.details
;
7193 HReg old
= lookupIRTemp(env
, cas
->oldLo
);
7194 HReg addr
= iselWordExpr_R(env
, cas
->addr
);
7195 HReg expd
= iselWordExpr_R(env
, cas
->expdLo
);
7196 HReg data
= iselWordExpr_R(env
, cas
->dataLo
);
7197 if (typeOfIRTemp(env
->type_env
, cas
->oldLo
) == Ity_I64
) {
7198 addInstr(env
, MIPSInstr_Cas(8, old
, addr
, expd
, data
, mode64
));
7199 } else if (typeOfIRTemp(env
->type_env
, cas
->oldLo
) == Ity_I32
) {
7200 addInstr(env
, MIPSInstr_Cas(4, old
, addr
, expd
, data
, mode64
));
7205 /* --------- INSTR MARK --------- */
7206 /* Doesn't generate any executable code ... */
7210 /* --------- ABI HINT --------- */
7211 /* These have no meaning (denotation in the IR) and so we ignore
7212 them ... if any actually made it this far. */
7216 /* --------- NO-OP --------- */
7217 /* Fairly self-explanatory, wouldn't you say? */
7221 /* --------- EXIT --------- */
7223 IRConst
* dst
= stmt
->Ist
.Exit
.dst
;
7224 if (!mode64
&& dst
->tag
!= Ico_U32
)
7225 vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
7226 if (mode64
&& dst
->tag
!= Ico_U64
)
7227 vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
7229 MIPSCondCode cc
= iselCondCode(env
, stmt
->Ist
.Exit
.guard
);
7230 MIPSAMode
* amPC
= MIPSAMode_IR(stmt
->Ist
.Exit
.offsIP
,
7231 GuestStatePointer(mode64
));
7233 /* Case: boring transfer to known address */
7234 if (stmt
->Ist
.Exit
.jk
== Ijk_Boring
7235 || stmt
->Ist
.Exit
.jk
== Ijk_Call
7236 /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
7237 if (env
->chainingAllowed
) {
7238 /* .. almost always true .. */
7239 /* Skip the event check at the dst if this is a forwards
7243 ? (((Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U64
) > (Addr64
)env
->max_ga
)
7244 : (((Addr32
)stmt
->Ist
.Exit
.dst
->Ico
.U32
) > (Addr32
)env
->max_ga
);
7245 if (0) vex_printf("%s", toFastEP
? "Y" : ",");
7246 addInstr(env
, MIPSInstr_XDirect(
7247 mode64
? (Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U64
7248 : (Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U32
,
7249 amPC
, cc
, toFastEP
));
7251 /* .. very occasionally .. */
7252 /* We can't use chaining, so ask for an assisted transfer,
7253 as that's the only alternative that is allowable. */
7254 HReg r
= iselWordExpr_R(env
, IRExpr_Const(stmt
->Ist
.Exit
.dst
));
7255 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, cc
, Ijk_Boring
));
7260 /* Case: assisted transfer to arbitrary address */
7261 switch (stmt
->Ist
.Exit
.jk
) {
7262 /* Keep this list in sync with that in iselNext below */
7271 case Ijk_SigFPE_IntDiv
:
7272 case Ijk_SigFPE_IntOvf
:
7273 case Ijk_Sys_syscall
:
7274 case Ijk_InvalICache
:
7276 HReg r
= iselWordExpr_R(env
, IRExpr_Const(stmt
->Ist
.Exit
.dst
));
7277 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, cc
,
7278 stmt
->Ist
.Exit
.jk
));
7285 /* Do we ever expect to see any other kind? */
7294 vex_printf("stmt_fail tag: 0x%x\n", stmt
->tag
);
7296 vpanic("iselStmt:\n");
7299 /*---------------------------------------------------------*/
7300 /*--- ISEL: Basic block terminators (Nexts) ---*/
7301 /*---------------------------------------------------------*/
7303 static void iselNext ( ISelEnv
* env
,
7304 IRExpr
* next
, IRJumpKind jk
, Int offsIP
)
7306 if (vex_traceflags
& VEX_TRACE_VCODE
) {
7307 vex_printf( "\n-- PUT(%d) = ", offsIP
);
7309 vex_printf( "; exit-");
7314 /* Case: boring transfer to known address */
7315 if (next
->tag
== Iex_Const
) {
7316 IRConst
* cdst
= next
->Iex
.Const
.con
;
7317 vassert(cdst
->tag
== (env
->mode64
? Ico_U64
:Ico_U32
));
7318 if (jk
== Ijk_Boring
|| jk
== Ijk_Call
) {
7319 /* Boring transfer to known address */
7320 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
, GuestStatePointer(env
->mode64
));
7321 if (env
->chainingAllowed
) {
7322 /* .. almost always true .. */
7323 /* Skip the event check at the dst if this is a forwards
7327 ? (((Addr64
)cdst
->Ico
.U64
) > (Addr64
)env
->max_ga
)
7328 : (((Addr32
)cdst
->Ico
.U32
) > (Addr32
)env
->max_ga
);
7329 if (0) vex_printf("%s", toFastEP
? "X" : ".");
7330 addInstr(env
, MIPSInstr_XDirect(
7331 env
->mode64
? (Addr64
)cdst
->Ico
.U64
7332 : (Addr64
)cdst
->Ico
.U32
,
7333 amPC
, MIPScc_AL
, toFastEP
));
7335 /* .. very occasionally .. */
7336 /* We can't use chaining, so ask for an assisted transfer,
7337 as that's the only alternative that is allowable. */
7338 HReg r
= iselWordExpr_R(env
, next
);
7339 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
,
7346 /* Case: call/return (==boring) transfer to any address */
7348 case Ijk_Boring
: case Ijk_Ret
: case Ijk_Call
: {
7349 HReg r
= iselWordExpr_R(env
, next
);
7350 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
,
7351 GuestStatePointer(env
->mode64
));
7352 if (env
->chainingAllowed
) {
7353 addInstr(env
, MIPSInstr_XIndir(r
, amPC
, MIPScc_AL
));
7355 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
,
7364 /* Case: assisted transfer to arbitrary address */
7366 /* Keep this list in sync with that for Ist_Exit above */
7375 case Ijk_SigFPE_IntDiv
:
7376 case Ijk_SigFPE_IntOvf
:
7377 case Ijk_Sys_syscall
:
7378 case Ijk_InvalICache
: {
7379 HReg r
= iselWordExpr_R(env
, next
);
7380 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
, GuestStatePointer(env
->mode64
));
7381 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
, jk
));
7388 vex_printf("\n-- PUT(%d) = ", offsIP
);
7390 vex_printf("; exit-");
7393 vassert(0); /* are we expecting any other kind? */
7396 /*---------------------------------------------------------*/
7397 /*--- Insn selector top-level ---*/
7398 /*---------------------------------------------------------*/
7400 /* Translate an entire BB to mips code. */
7401 HInstrArray
*iselSB_MIPS ( const IRSB
* bb
,
7403 const VexArchInfo
* archinfo_host
,
7404 const VexAbiInfo
* vbi
,
7405 Int offs_Host_EvC_Counter
,
7406 Int offs_Host_EvC_FailAddr
,
7407 Bool chainingAllowed
,
7414 MIPSAMode
*amCounter
, *amFailAddr
;
7416 hwcaps_host
= archinfo_host
->hwcaps
;
7419 vassert(arch_host
== VexArchMIPS32
|| arch_host
== VexArchMIPS64
);
7420 vassert(VEX_PRID_COMP_MIPS
== VEX_MIPS_COMP_ID(hwcaps_host
)
7421 || VEX_PRID_COMP_CAVIUM
== VEX_MIPS_COMP_ID(hwcaps_host
)
7422 || VEX_PRID_COMP_BROADCOM
== VEX_MIPS_COMP_ID(hwcaps_host
)
7423 || VEX_PRID_COMP_NETLOGIC
== VEX_MIPS_COMP_ID(hwcaps_host
)
7424 || VEX_PRID_COMP_INGENIC_E1
== VEX_MIPS_COMP_ID(hwcaps_host
)
7425 || VEX_PRID_COMP_LEGACY
== VEX_MIPS_COMP_ID(hwcaps_host
));
7427 /* Check that the host's endianness is as expected. */
7428 vassert(archinfo_host
->endness
== VexEndnessLE
7429 || archinfo_host
->endness
== VexEndnessBE
);
7431 mode64
= arch_host
!= VexArchMIPS32
;
7432 fp_mode64
= VEX_MIPS_HOST_FP_MODE(hwcaps_host
);
7433 has_msa
= VEX_MIPS_PROC_MSA(archinfo_host
->hwcaps
);
7435 /* Make up an initial environment to use. */
7436 env
= LibVEX_Alloc_inline(sizeof(ISelEnv
));
7438 env
->mode64
= mode64
;
7439 env
->fp_mode64
= fp_mode64
;
7441 /* Set up output code array. */
7442 env
->code
= newHInstrArray();
7444 /* Copy BB's type env. */
7445 env
->type_env
= bb
->tyenv
;
7447 /* Make up an IRTemp -> virtual HReg mapping. This doesn't
7448 change as we go along. */
7449 env
->n_vregmap
= bb
->tyenv
->types_used
;
7450 env
->vregmap
= LibVEX_Alloc_inline(env
->n_vregmap
* sizeof(HReg
));
7451 env
->vregmapHI
= LibVEX_Alloc_inline(env
->n_vregmap
* sizeof(HReg
));
7453 /* and finally ... */
7454 env
->hwcaps
= hwcaps_host
;
7455 env
->chainingAllowed
= chainingAllowed
;
7456 env
->hwcaps
= hwcaps_host
;
7457 env
->max_ga
= max_ga
;
7459 /* For each IR temporary, allocate a suitably-kinded virtual
7462 for (i
= 0; i
< env
->n_vregmap
; i
++) {
7463 hregHI
= hreg
= INVALID_HREG
;
7464 switch (bb
->tyenv
->types
[i
]) {
7470 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7473 hreg
= mkHReg(True
, HRcInt32
, 0, j
++);
7478 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7481 hreg
= mkHReg(True
, HRcInt32
, 0, j
++);
7482 hregHI
= mkHReg(True
, HRcInt32
, 0, j
++);
7487 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7488 hregHI
= mkHReg(True
, HRcInt64
, 0, j
++);
7492 hreg
= mkHReg(True
, HRcFlt64
, 0, j
++);
7495 hreg
= mkHReg(True
, HRcFlt32
, 0, j
++);
7499 hreg
= mkHReg(True
, HRcFlt64
, 0, j
++);
7502 hreg
= mkHReg(True
, HRcVec128
, 0, j
++);
7505 ppIRType(bb
->tyenv
->types
[i
]);
7506 vpanic("iselBB(mips): IRTemp type");
7509 env
->vregmap
[i
] = hreg
;
7510 env
->vregmapHI
[i
] = hregHI
;
7514 /* The very first instruction must be an event check. */
7515 amCounter
= MIPSAMode_IR(offs_Host_EvC_Counter
, GuestStatePointer(mode64
));
7516 amFailAddr
= MIPSAMode_IR(offs_Host_EvC_FailAddr
, GuestStatePointer(mode64
));
7517 addInstr(env
, MIPSInstr_EvCheck(amCounter
, amFailAddr
));
7519 /* Possibly a block counter increment (for profiling). At this
7520 point we don't know the address of the counter, so just pretend
7521 it is zero. It will have to be patched later, but before this
7522 translation is used, by a call to LibVEX_patchProfCtr. */
7524 addInstr(env
, MIPSInstr_ProfInc());
7527 /* Ok, finally we can iterate over the statements. */
7528 for (i
= 0; i
< bb
->stmts_used
; i
++)
7529 iselStmt(env
, bb
->stmts
[i
]);
7531 iselNext(env
, bb
->next
, bb
->jumpkind
, bb
->offsIP
);
7533 /* record the number of vregs we used. */
7534 env
->code
->n_vregs
= env
->vreg_ctr
;
7539 /*---------------------------------------------------------------*/
7540 /*--- end host_mips_isel.c ---*/
7541 /*---------------------------------------------------------------*/