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
11 mips-valgrind@rt-rk.com
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "libvex_basictypes.h"
32 #include "libvex_ir.h"
35 #include "main_util.h"
36 #include "main_globals.h"
37 #include "host_generic_regs.h"
38 #include "host_generic_simd64.h" /* for 64-bit SIMD helpers */
39 #include "host_mips_defs.h"
41 /*---------------------------------------------------------*/
42 /*--- Register Usage Conventions ---*/
43 /*---------------------------------------------------------*/
53 static Bool mode64
= False
;
55 /* Host CPU has FPU and 32 dbl. prec. FP registers. */
56 static Bool fp_mode64
= False
;
59 static UInt hwcaps_host
= 0;
61 /* Host CPU has MSA ASE */
62 static Bool has_msa
= False
;
64 /* GPR register class for mips32/64 */
65 #define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
67 /* FPR register class for mips32/64 */
68 #define HRcFPR(_mode64) ((_mode64) ? HRcFlt64 : HRcFlt32)
70 /*---------------------------------------------------------*/
72 /*---------------------------------------------------------*/
74 /* This carries around:
76 - A mapping from IRTemp to IRType, giving the type of any IRTemp we
77 might encounter. This is computed before insn selection starts,
80 - A mapping from IRTemp to HReg. This tells the insn selector
81 which virtual register(s) are associated with each IRTemp
82 temporary. This is computed before insn selection starts, and
83 does not change. We expect this mapping to map precisely the
84 same set of IRTemps as the type mapping does.
86 - vregmap holds the primary register for the IRTemp.
87 - vregmapHI is only used for 64-bit integer-typed
88 IRTemps. It holds the identity of a second
89 32-bit virtual HReg, which holds the high half
92 - The code array, that is, the insns selected so far.
94 - A counter, for generating new virtual registers.
96 - The host subarchitecture we are selecting insns for.
97 This is set at the start and does not change.
99 - A Bool for indicating whether we may generate chain-me
100 instructions for control flow transfers, or whether we must use
103 - The maximum guest address of any guest insn in this block.
104 Actually, the address of the highest-addressed byte from any insn
105 in this block. Is set at the start and does not change. This is
106 used for detecting jumps which are definitely forward-edges from
107 this block, and therefore can be made (chained) to the fast entry
108 point of the destination, thereby avoiding the destination's
111 Note, this is all (well, mostly) host-independent.
116 /* Constant -- are set at the start and do not change. */
127 Bool chainingAllowed
;
130 /* These are modified as we go along. */
136 static HReg
lookupIRTemp(ISelEnv
* env
, IRTemp tmp
)
138 vassert(tmp
< env
->n_vregmap
);
139 return env
->vregmap
[tmp
];
142 static void lookupIRTemp64(HReg
* vrHI
, HReg
* vrLO
, ISelEnv
* env
, IRTemp tmp
)
144 vassert(tmp
< env
->n_vregmap
);
145 vassert(! hregIsInvalid(env
->vregmapHI
[tmp
]));
146 *vrLO
= env
->vregmap
[tmp
];
147 *vrHI
= env
->vregmapHI
[tmp
];
151 lookupIRTempPair(HReg
* vrHI
, HReg
* vrLO
, ISelEnv
* env
, IRTemp tmp
)
153 vassert(env
->mode64
);
154 vassert(tmp
< env
->n_vregmap
);
155 vassert(! hregIsInvalid(env
->vregmapHI
[tmp
]));
156 *vrLO
= env
->vregmap
[tmp
];
157 *vrHI
= env
->vregmapHI
[tmp
];
160 static void addInstr(ISelEnv
* env
, MIPSInstr
* instr
)
162 addHInstr(env
->code
, instr
);
163 if (vex_traceflags
& VEX_TRACE_VCODE
) {
164 ppMIPSInstr(instr
, mode64
);
169 static HReg
newVRegI(ISelEnv
* env
)
171 HReg reg
= mkHReg(True
/*virtual reg*/,
172 HRcGPR(env
->mode64
), 0/*enc*/, env
->vreg_ctr
);
177 static HReg
newVRegD(ISelEnv
* env
)
179 HReg reg
= mkHReg(True
/*virtual reg*/,
180 HRcFlt64
, 0/*enc*/, env
->vreg_ctr
);
185 static HReg
newVRegF(ISelEnv
* env
)
187 HReg reg
= mkHReg(True
/*virtual reg*/,
188 HRcFPR(env
->mode64
), 0/*enc*/, env
->vreg_ctr
);
193 static HReg
newVRegV ( ISelEnv
* env
)
195 HReg reg
= mkHReg(True
/*virtual reg*/, HRcVec128
, 0, env
->vreg_ctr
);
200 static void add_to_sp(ISelEnv
* env
, UInt n
)
202 HReg sp
= StackPointer(mode64
);
203 vassert(n
< 256 && (n
% 8) == 0);
205 addInstr(env
, MIPSInstr_Alu(Malu_DADD
, sp
, sp
, MIPSRH_Imm(True
,
208 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, sp
, sp
, MIPSRH_Imm(True
,
212 static void sub_from_sp(ISelEnv
* env
, UInt n
)
214 HReg sp
= StackPointer(mode64
);
215 vassert(n
< 256 && (n
% 8) == 0);
217 addInstr(env
, MIPSInstr_Alu(Malu_DSUB
, sp
, sp
,
218 MIPSRH_Imm(True
, toUShort(n
))));
220 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, sp
, sp
,
221 MIPSRH_Imm(True
, toUShort(n
))));
224 /*---------------------------------------------------------*/
225 /*--- ISEL: Forward declarations ---*/
226 /*---------------------------------------------------------*/
228 /* These are organised as iselXXX and iselXXX_wrk pairs. The
229 iselXXX_wrk do the real work, but are not to be called directly.
230 For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
231 checks that all returned registers are virtual. You should not
232 call the _wrk version directly.
234 /* 32-bit mode: Compute an I8/I16/I32 into a RH
235 (reg-or-halfword-immediate).
236 It's important to specify whether the immediate is to be regarded
237 as signed or not. If yes, this will never return -32768 as an
238 immediate; this guaranteed that all signed immediates that are
239 return can have their sign inverted if need be.
241 static MIPSRH
*iselWordExpr_RH_wrk(ISelEnv
* env
, Bool syned
, IRExpr
* e
);
242 static MIPSRH
*iselWordExpr_RH(ISelEnv
* env
, Bool syned
, IRExpr
* e
);
244 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
245 immediate in the range 1 .. 31 inclusive. Used for doing shift amounts. */
246 static MIPSRH
*iselWordExpr_RH5u_wrk(ISelEnv
* env
, IRExpr
* e
);
247 static MIPSRH
*iselWordExpr_RH5u(ISelEnv
* env
, IRExpr
* e
);
249 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
250 immediate in the range 1 .. 63 inclusive. Used for doing shift amounts. */
251 static MIPSRH
*iselWordExpr_RH6u_wrk(ISelEnv
* env
, IRExpr
* e
);
252 static MIPSRH
*iselWordExpr_RH6u(ISelEnv
* env
, IRExpr
* e
);
254 /* Compute an I8 into a reg-or-7-bit-unsigned-immediate, the latter being an
255 immediate in the range 1 .. 127 inclusive. Used for doing shift amounts. */
256 static MIPSRH
*iselWordExpr_RH7u_wrk(ISelEnv
* env
, IRExpr
* e
);
257 static MIPSRH
*iselWordExpr_RH7u(ISelEnv
* env
, IRExpr
* e
);
259 /* compute an I8/I16/I32 into a GPR*/
260 static HReg
iselWordExpr_R_wrk(ISelEnv
* env
, IRExpr
* e
);
261 static HReg
iselWordExpr_R(ISelEnv
* env
, IRExpr
* e
);
263 /* compute an I32 into an AMode. */
264 static MIPSAMode
*iselWordExpr_AMode_wrk(ISelEnv
* env
, IRExpr
* e
,
266 static MIPSAMode
*iselWordExpr_AMode(ISelEnv
* env
, IRExpr
* e
, IRType xferTy
);
268 static void iselInt64Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
,
270 static void iselInt64Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
);
272 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
273 static void iselInt128Expr_wrk(HReg
* rHi
, HReg
* rLo
,
274 ISelEnv
* env
, IRExpr
* e
);
275 static void iselInt128Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
);
277 static HReg
iselV128Expr( ISelEnv
* env
, IRExpr
* e
);
278 static HReg
iselV128Expr_wrk( ISelEnv
* env
, IRExpr
* e
);
280 static MIPSCondCode
iselCondCode_wrk(ISelEnv
* env
, IRExpr
* e
);
281 static MIPSCondCode
iselCondCode(ISelEnv
* env
, IRExpr
* e
);
283 static HReg
iselDblExpr_wrk(ISelEnv
* env
, IRExpr
* e
);
284 static HReg
iselDblExpr(ISelEnv
* env
, IRExpr
* e
);
286 static HReg
iselFltExpr_wrk(ISelEnv
* env
, IRExpr
* e
);
287 static HReg
iselFltExpr(ISelEnv
* env
, IRExpr
* e
);
289 static void set_MIPS_rounding_mode(ISelEnv
* env
, IRExpr
* mode
)
292 rounding mode | MIPS | IR
293 ------------------------
296 to +infinity | 10 | 10
297 to -infinity | 11 | 01
299 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
300 HReg irrm
= iselWordExpr_R(env
, mode
);
301 HReg tmp
= newVRegI(env
);
302 HReg fcsr_old
= newVRegI(env
);
305 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, irrm
,
306 MIPSRH_Imm(False
, 1)));
307 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, tmp
, irrm
, MIPSRH_Reg(tmp
)));
308 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
, MIPSRH_Imm(False
, 3)));
309 /* save old value of FCSR */
310 addInstr(env
, MIPSInstr_MfFCSR(fcsr_old
));
311 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
312 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
314 /* store old FCSR to stack */
315 addInstr(env
, MIPSInstr_Store(4, am_addr
, fcsr_old
, mode64
));
317 /* set new value of FCSR */
318 addInstr(env
, MIPSInstr_MtFCSR(tmp
));
321 static void set_MIPS_rounding_mode_MSA(ISelEnv
* env
, IRExpr
* mode
) {
323 rounding mode | MIPS | IR
324 ------------------------
327 to +infinity | 10 | 10
328 to -infinity | 11 | 01
330 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
331 HReg irrm
= iselWordExpr_R(env
, mode
);
332 HReg tmp
= newVRegI(env
);
333 HReg msacsr_old
= newVRegI(env
);
335 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, irrm
,
336 MIPSRH_Imm(False
, 1)));
337 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, tmp
, irrm
, MIPSRH_Reg(tmp
)));
338 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
, MIPSRH_Imm(False
, 3)));
339 /* save old value of MSACSR */
340 addInstr(env
, MIPSInstr_MsaElm(MSA_CFCMSA
, hregMIPS_GPR0(mode64
), msacsr_old
,
342 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
343 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
344 /* store old MSACSR to stack */
345 addInstr(env
, MIPSInstr_Store(4, am_addr
, msacsr_old
, mode64
));
346 /* set new value of MSACSR */
347 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, tmp
, hregMIPS_GPR0(mode64
),
352 static void set_guest_MIPS_rounding_mode_MSA(ISelEnv
* env
) {
354 rounding mode | MIPS | IR
355 ------------------------
358 to +infinity | 10 | 10
359 to -infinity | 11 | 01
361 /* rm_MIPS32 = XOR(rm_IR , (rm_IR << 1)) & 3 */
362 HReg irrm
= newVRegI(env
);
363 HReg msacsr_old
= newVRegI(env
);
365 MIPSAMode
*rm_addr
= MIPSAMode_IR(MSACSR_OFFSET(mode64
),
366 GuestStatePointer(mode64
));
367 addInstr(env
, MIPSInstr_Load(4, irrm
, rm_addr
, mode64
));
368 /* save old value of MSACSR */
369 addInstr(env
, MIPSInstr_MsaElm(MSA_CFCMSA
, hregMIPS_GPR0(mode64
), msacsr_old
,
371 sub_from_sp(env
, 8); /* Move SP down 8 bytes */
372 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
373 /* store old MSACSR to stack */
374 addInstr(env
, MIPSInstr_Store(4, am_addr
, msacsr_old
, mode64
));
375 /* set new value of MSACSR */
376 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, irrm
, hregMIPS_GPR0(mode64
),
381 static void set_MIPS_rounding_default(ISelEnv
* env
)
383 HReg fcsr
= newVRegI(env
);
386 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
388 addInstr(env
, MIPSInstr_Load(4, fcsr
, am_addr
, mode64
));
390 add_to_sp(env
, 8); /* Reset SP */
392 /* set new value of FCSR*/
393 addInstr(env
, MIPSInstr_MtFCSR(fcsr
));
396 static void set_MIPS_rounding_default_MSA(ISelEnv
* env
) {
397 HReg msacsr
= newVRegI(env
);
400 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
401 addInstr(env
, MIPSInstr_Load(4, msacsr
, am_addr
, mode64
));
402 add_to_sp(env
, 8); /* Reset SP */
403 /* set new value of FCSR*/
404 addInstr(env
, MIPSInstr_MsaElm(MSA_CTCMSA
, msacsr
, hregMIPS_GPR0(mode64
),
408 /*---------------------------------------------------------*/
409 /*--- ISEL: Misc helpers ---*/
410 /*---------------------------------------------------------*/
412 /* Make an int reg-reg move. */
413 static MIPSInstr
*mk_iMOVds_RR(HReg r_dst
, HReg r_src
)
415 vassert(hregClass(r_dst
) == hregClass(r_src
));
416 vassert(hregClass(r_src
) == HRcInt32
|| hregClass(r_src
) == HRcInt64
);
417 return MIPSInstr_Alu(Malu_OR
, r_dst
, r_src
, MIPSRH_Reg(r_src
));
420 /*---------------------------------------------------------*/
421 /*--- ISEL: Function call helpers ---*/
422 /*---------------------------------------------------------*/
424 /* Used only in doHelperCall. See big comment in doHelperCall re
425 handling of register-parameter args. This function figures out
426 whether evaluation of an expression might require use of a fixed
427 register. If in doubt return True (safe but suboptimal).
429 static Bool
mightRequireFixedRegs(IRExpr
* e
)
441 /* Load 2*I32 regs to fp reg */
442 static HReg
mk_LoadRR32toFPR(ISelEnv
* env
, HReg r_srcHi
, HReg r_srcLo
)
444 HReg fr_dst
= newVRegD(env
);
445 MIPSAMode
*am_addr0
, *am_addr1
;
447 vassert(hregClass(r_srcHi
) == HRcInt32
);
448 vassert(hregClass(r_srcLo
) == HRcInt32
);
450 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
451 am_addr0
= MIPSAMode_IR(0, StackPointer(mode64
));
452 am_addr1
= MIPSAMode_IR(4, StackPointer(mode64
));
454 /* store hi,lo as Ity_I32's */
455 #if defined (_MIPSEL)
456 addInstr(env
, MIPSInstr_Store(4, am_addr0
, r_srcLo
, mode64
));
457 addInstr(env
, MIPSInstr_Store(4, am_addr1
, r_srcHi
, mode64
));
458 #elif defined (_MIPSEB)
459 addInstr(env
, MIPSInstr_Store(4, am_addr0
, r_srcHi
, mode64
));
460 addInstr(env
, MIPSInstr_Store(4, am_addr1
, r_srcLo
, mode64
));
462 /* Stop gcc on other platforms complaining about am_addr1 being set
468 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, fr_dst
, am_addr0
));
470 add_to_sp(env
, 16); /* Reset SP */
474 /* Do a complete function call. |guard| is a Ity_Bit expression
475 indicating whether or not the call happens. If guard==NULL, the
476 call is unconditional. |retloc| is set to indicate where the
477 return value is after the call. The caller (of this fn) must
478 generate code to add |stackAdjustAfterCall| to the stack pointer
479 after the call is done. */
481 static void doHelperCall(/*OUT*/UInt
* stackAdjustAfterCall
,
482 /*OUT*/RetLoc
* retloc
,
485 IRCallee
* cee
, IRType retTy
, IRExpr
** args
)
491 Int n_args
, i
, argreg
;
493 HReg src
= INVALID_HREG
;
495 /* Set default returns. We'll update them later if needed. */
496 *stackAdjustAfterCall
= 0;
497 *retloc
= mk_RetLoc_INVALID();
499 /* These are used for cross-checking that IR-level constraints on
500 the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
504 /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
505 are allowed to be used for passing integer arguments. They correspond
506 to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
507 on MIPS host (since we only implement one calling convention) and so we
510 /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
511 are allowed to be used for passing integer arguments. They correspond
512 to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
513 on MIPS host (since we only implement one calling convention) and so we
516 /* The return type can be I{64,32,16,8} or V{128,256}. In the
517 latter two cases, it is expected that |args| will contain the
518 special node IRExpr_VECRET(), in which case this routine
519 generates code to allocate space on the stack for the vector
520 return value. Since we are not passing any scalars on the
521 stack, it is enough to preallocate the return space before
522 marshalling any arguments, in this case.
524 |args| may also contain IRExpr_GSPTR(), in which case the value
525 in the guest state pointer register is passed as the
526 corresponding argument. */
529 for (i
= 0; args
[i
]; i
++) {
530 IRExpr
* arg
= args
[i
];
531 if (UNLIKELY(arg
->tag
== Iex_VECRET
)) {
533 } else if (UNLIKELY(arg
->tag
== Iex_GSPTR
)) {
539 if (n_args
> MIPS_N_REGPARMS
) {
540 vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
543 argregs
[0] = hregMIPS_GPR4(mode64
);
544 argregs
[1] = hregMIPS_GPR5(mode64
);
545 argregs
[2] = hregMIPS_GPR6(mode64
);
546 argregs
[3] = hregMIPS_GPR7(mode64
);
547 argregs
[4] = hregMIPS_GPR8(mode64
);
548 argregs
[5] = hregMIPS_GPR9(mode64
);
549 argregs
[6] = hregMIPS_GPR10(mode64
);
550 argregs
[7] = hregMIPS_GPR11(mode64
);
552 tmpregs
[0] = tmpregs
[1] = tmpregs
[2] =
553 tmpregs
[3] = tmpregs
[4] = tmpregs
[5] =
554 tmpregs
[6] = tmpregs
[7] = INVALID_HREG
;
556 argregs
[0] = hregMIPS_GPR4(mode64
);
557 argregs
[1] = hregMIPS_GPR5(mode64
);
558 argregs
[2] = hregMIPS_GPR6(mode64
);
559 argregs
[3] = hregMIPS_GPR7(mode64
);
561 tmpregs
[0] = tmpregs
[1] = tmpregs
[2] = tmpregs
[3] = INVALID_HREG
;
564 /* First decide which scheme (slow or fast) is to be used. First assume the
565 fast scheme, and select slow if any contraindications (wow) appear. */
569 /* We'll need space on the stack for the return value. Avoid
570 possible complications with nested calls by using the slow
572 if (retTy
== Ity_V128
|| retTy
== Ity_V256
)
575 if (go_fast
&& guard
) {
576 if (guard
->tag
== Iex_Const
&& guard
->Iex
.Const
.con
->tag
== Ico_U1
577 && guard
->Iex
.Const
.con
->Ico
.U1
== True
) {
580 /* Not manifestly unconditional -- be conservative. */
586 for (i
= 0; i
< n_args
; i
++) {
587 if (mightRequireFixedRegs(args
[i
])) {
594 /* At this point the scheme to use has been established. Generate
595 code to get the arg values into the argument rregs. */
600 for (i
= 0; i
< n_args
; i
++) {
601 IRExpr
* arg
= args
[i
];
602 vassert(argreg
< MIPS_N_REGPARMS
);
604 IRType aTy
= Ity_INVALID
;
605 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg
)))
606 aTy
= typeOfIRExpr(env
->type_env
, arg
);
608 if (aTy
== Ity_I32
|| (mode64
&& aTy
!= Ity_INVALID
)) {
609 argiregs
|= (1 << (argreg
+ 4));
610 addInstr(env
, mk_iMOVds_RR(argregs
[argreg
],
611 iselWordExpr_R(env
, arg
)));
613 } else if (aTy
== Ity_I64
) { /* Ity_I64 */
616 argiregs
|= (1 << (argreg
+ 4));
619 iselInt64Expr(&rHi
, &rLo
, env
, arg
);
620 argiregs
|= (1 << (argreg
+ 4));
621 addInstr(env
, mk_iMOVds_RR( argregs
[argreg
++], rLo
));
622 argiregs
|= (1 << (argreg
+ 4));
623 addInstr(env
, mk_iMOVds_RR( argregs
[argreg
], rHi
));
625 } else if (arg
->tag
== Iex_GSPTR
) {
627 addInstr(env
, mk_iMOVds_RR(argregs
[argreg
],
628 GuestStatePointer(mode64
)));
630 } else if (arg
->tag
== Iex_VECRET
) {
631 // If this happens, it denotes ill-formed IR.
635 /* Fast scheme only applies for unconditional calls. Hence: */
638 /* SLOW SCHEME; move via temporaries */
641 for (i
= 0; i
< n_args
; i
++) {
642 vassert(argreg
< MIPS_N_REGPARMS
);
643 IRExpr
* arg
= args
[i
];
645 IRType aTy
= Ity_INVALID
;
646 if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg
)))
647 aTy
= typeOfIRExpr(env
->type_env
, arg
);
649 if (aTy
== Ity_I32
|| (mode64
&& aTy
!= Ity_INVALID
)) {
650 tmpregs
[argreg
] = iselWordExpr_R(env
, arg
);
652 } else if (aTy
== Ity_I64
) { /* Ity_I64 */
655 if (argreg
+ 1 >= MIPS_N_REGPARMS
)
656 vassert(0); /* out of argregs */
658 iselInt64Expr(&raHi
, &raLo
, env
, arg
);
659 tmpregs
[argreg
] = raLo
;
661 tmpregs
[argreg
] = raHi
;
663 } else if (arg
->tag
== Iex_GSPTR
) {
664 tmpregs
[argreg
] = GuestStatePointer(mode64
);
667 else if (arg
->tag
== Iex_VECRET
) {
668 tmpregs
[argreg
++] = StackPointer(mode64
);
669 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
673 /* Now we can compute the condition. We can't do it earlier
674 because the argument computations could trash the condition
675 codes. Be a bit clever to handle the common case where the
679 if (guard
->tag
== Iex_Const
&& guard
->Iex
.Const
.con
->tag
== Ico_U1
680 && guard
->Iex
.Const
.con
->Ico
.U1
== True
) {
681 /* unconditional -- do nothing */
683 cc
= iselCondCode(env
, guard
);
684 src
= iselWordExpr_R(env
, guard
);
687 /* Move the args to their final destinations. */
688 for (i
= 0; i
< argreg
; i
++) {
689 if (hregIsInvalid(tmpregs
[i
])) /* Skip invalid regs */
691 /* None of these insns, including any spill code that might
692 be generated, may alter the condition codes. */
693 argiregs
|= (1 << (i
+ 4));
694 addInstr(env
, mk_iMOVds_RR(argregs
[i
], tmpregs
[i
]));
698 /* Do final checks, set the return values, and generate the call
699 instruction proper. */
700 vassert(nGSPTRs
== 0 || nGSPTRs
== 1);
701 vassert(nVECRETs
== ((retTy
== Ity_V128
|| retTy
== Ity_V256
) ? 1 : 0));
702 vassert(*stackAdjustAfterCall
== 0);
703 vassert(is_RetLoc_INVALID(*retloc
));
706 /* Function doesn't return a value. */
707 *retloc
= mk_RetLoc_simple(RLPri_None
);
710 *retloc
= mk_RetLoc_simple(mode64
? RLPri_Int
: RLPri_2Int
);
712 case Ity_I32
: case Ity_I16
: case Ity_I8
:
713 *retloc
= mk_RetLoc_simple(RLPri_Int
);
716 *retloc
= mk_RetLoc_spRel(RLPri_V128SpRel
, 0);
717 *stackAdjustAfterCall
= 16;
721 *retloc
= mk_RetLoc_spRel(RLPri_V256SpRel
, 0);
722 *stackAdjustAfterCall
= 32;
725 /* IR can denote other possible return types, but we don't
726 handle those here. */
730 Addr64 target
= mode64
? (Addr
)cee
->addr
:
731 toUInt((Addr
)cee
->addr
);
733 /* Finally, generate the call itself. This needs the *retloc value
734 set in the switch above, which is why it's at the end. */
736 addInstr(env
, MIPSInstr_CallAlways(cc
, target
, argiregs
,
739 addInstr(env
, MIPSInstr_Call(cc
, target
, argiregs
, src
, *retloc
));
742 /*---------------------------------------------------------*/
743 /*--- ISEL: Integer expression auxiliaries ---*/
744 /*---------------------------------------------------------*/
746 /* --------------------- AMODEs --------------------- */
748 /* Return an AMode which computes the value of the specified
749 expression, possibly also adding insns to the code list as a
750 result. The expression may only be a word-size one.
753 static Bool
uInt_fits_in_16_bits(UInt u
)
758 return toBool(u
== (UInt
) i
);
761 static Bool
uLong_fits_in_16_bits ( ULong u
)
763 Long i
= u
& 0xFFFFULL
;
766 return toBool(u
== (ULong
) i
);
769 static Bool
uLong_is_4_aligned ( ULong u
)
771 return toBool((u
& 3ULL) == 0);
774 static Bool
sane_AMode(ISelEnv
* env
, MIPSAMode
* am
)
778 return toBool(hregClass(am
->Mam
.IR
.base
) == HRcGPR(mode64
) &&
779 hregIsVirtual(am
->Mam
.IR
.base
) &&
780 uInt_fits_in_16_bits(am
->Mam
.IR
.index
));
782 return toBool(hregClass(am
->Mam
.RR
.base
) == HRcGPR(mode64
) &&
783 hregIsVirtual(am
->Mam
.RR
.base
) &&
784 hregClass(am
->Mam
.RR
.index
) == HRcGPR(mode64
) &&
785 hregIsVirtual(am
->Mam
.RR
.index
));
787 vpanic("sane_AMode: unknown mips amode tag");
791 static MIPSAMode
*iselWordExpr_AMode(ISelEnv
* env
, IRExpr
* e
, IRType xferTy
)
793 MIPSAMode
*am
= iselWordExpr_AMode_wrk(env
, e
, xferTy
);
794 vassert(sane_AMode(env
, am
));
798 /* DO NOT CALL THIS DIRECTLY ! */
799 static MIPSAMode
*iselWordExpr_AMode_wrk(ISelEnv
* env
, IRExpr
* e
,
802 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
804 Bool aligned4imm
= toBool(xferTy
== Ity_I32
|| xferTy
== Ity_I64
);
805 vassert(ty
== Ity_I64
);
807 /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
808 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add64
809 && e
->Iex
.Binop
.arg2
->tag
== Iex_Const
810 && e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U64
812 uLong_is_4_aligned(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
) : True
)
813 && uLong_fits_in_16_bits(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
)) {
814 return MIPSAMode_IR((Int
) e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U64
,
815 iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
));
818 /* Add64(expr,expr) */
819 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add64
) {
820 HReg r_base
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
821 HReg r_idx
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
822 return MIPSAMode_RR(r_idx
, r_base
);
825 vassert(ty
== Ity_I32
);
827 /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
828 if (e
->tag
== Iex_Binop
829 && e
->Iex
.Binop
.op
== Iop_Add32
830 && e
->Iex
.Binop
.arg2
->tag
== Iex_Const
831 && e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U32
832 && uInt_fits_in_16_bits(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
-> Ico
.U32
)) {
833 return MIPSAMode_IR((Int
) e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U32
,
834 iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
));
837 /* Add32(expr,expr) */
838 if (e
->tag
== Iex_Binop
&& e
->Iex
.Binop
.op
== Iop_Add32
) {
839 HReg r_base
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
840 HReg r_idx
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
842 return MIPSAMode_RR(r_idx
, r_base
);
846 /* Doesn't match anything in particular. Generate it into
847 a register and use that. */
848 return MIPSAMode_IR(0, iselWordExpr_R(env
, e
));
851 /*---------------------------------------------------------*/
852 /*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/
853 /*---------------------------------------------------------*/
855 /* Select insns for an integer-typed expression, and add them to the
856 code list. Return a reg holding the result. This reg will be a
857 virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you
858 want to modify it, ask for a new vreg, copy it in there, and modify
859 the copy. The register allocator will do its best to map both
860 vregs to the same real register, so the copies will often disappear
863 This should handle expressions of 64, 32, 16 and 8-bit type.
864 All results are returned in a (mode64 ? 64bit : 32bit) register.
865 For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
866 are arbitrary, so you should mask or sign extend partial values
869 static HReg
iselWordExpr_R(ISelEnv
* env
, IRExpr
* e
)
871 HReg r
= iselWordExpr_R_wrk(env
, e
);
872 /* sanity checks ... */
874 vassert(hregClass(r
) == HRcGPR(env
->mode64
));
875 vassert(hregIsVirtual(r
));
879 /* DO NOT CALL THIS DIRECTLY ! */
880 static HReg
iselWordExpr_R_wrk(ISelEnv
* env
, IRExpr
* e
)
883 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
884 vassert(ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
|| ty
== Ity_I1
885 || ty
== Ity_F32
|| (ty
== Ity_I64
&& mode64
)
886 || (ty
== Ity_I128
&& mode64
));
889 /* --------- TEMP --------- */
891 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
893 /* --------- LOAD --------- */
895 HReg r_dst
= newVRegI(env
);
896 MIPSAMode
*am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
898 if (e
->Iex
.Load
.end
!= Iend_LE
899 && e
->Iex
.Load
.end
!= Iend_BE
)
902 addInstr(env
, MIPSInstr_Load(toUChar(sizeofIRType(ty
)),
903 r_dst
, am_addr
, mode64
));
907 /* --------- BINARY OP --------- */
912 /* Is it an addition or logical style op? */
913 switch (e
->Iex
.Binop
.op
) {
956 aluOp
= Malu_INVALID
;
960 /* For commutative ops we assume any literal
961 values are on the second operand. */
962 if (aluOp
!= Malu_INVALID
) {
963 HReg r_dst
= newVRegI(env
);
964 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
965 MIPSRH
*ri_srcR
= NULL
;
966 /* get right arg into an RH, in the appropriate way */
972 ri_srcR
= iselWordExpr_RH(env
, True
/*signed */ ,
978 ri_srcR
= iselWordExpr_RH(env
, False
/*unsigned */,
982 vpanic("iselWordExpr_R_wrk-aluOp-arg2");
984 addInstr(env
, MIPSInstr_Alu(aluOp
, r_dst
, r_srcL
, ri_srcR
));
989 switch (e
->Iex
.Binop
.op
) {
1005 shftOp
= Mshft_INVALID
;
1009 /* we assume any literal values are on the second operand. */
1010 if (shftOp
!= Mshft_INVALID
) {
1011 HReg r_dst
= newVRegI(env
);
1012 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1015 ri_srcR
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
1017 ri_srcR
= iselWordExpr_RH5u(env
, e
->Iex
.Binop
.arg2
);
1021 } else if (ty
== Ity_I16
) {
1022 if (shftOp
== Mshft_SRA
) {
1023 HReg tmp
= newVRegI(env
);
1024 HReg r_srcL_se
= newVRegI(env
);
1025 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
,
1026 r_srcL
, MIPSRH_Imm(False
, 16)));
1027 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, r_srcL_se
,
1028 tmp
, MIPSRH_Imm(False
, 16)));
1029 addInstr(env
, MIPSInstr_Shft(shftOp
, True
,
1030 r_dst
, r_srcL_se
, ri_srcR
));
1031 } else if (shftOp
== Mshft_SRL
) {
1032 HReg r_srcL_se
= newVRegI(env
);
1033 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcL_se
, r_srcL
,
1034 MIPSRH_Imm(False
, 0xFFFF)));
1035 addInstr(env
, MIPSInstr_Shft(shftOp
, True
,
1036 r_dst
, r_srcL_se
, ri_srcR
));
1040 } else if (ty
== Ity_I32
) {
1041 if (mode64
&& (shftOp
== Mshft_SRA
|| shftOp
== Mshft_SRL
)) {
1042 HReg tmp
= newVRegI(env
);
1043 HReg r_srcL_se
= newVRegI(env
);
1044 /* SRA, SRAV, SRL, SRLV: On 64-bit processors, if GPR rt does
1045 not contain a sign-extended 32-bit value (bits 63..31
1046 equal), then the result of the operation is UNPREDICTABLE.
1047 So we need to sign-extend r_srcL:
1048 DSLLV tmp, r_srcL, 32
1049 DSRAV r_srcL_se, tmp, 32
1051 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tmp
,
1052 r_srcL
, MIPSRH_Imm(False
, 32)));
1053 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
, r_srcL_se
,
1054 tmp
, MIPSRH_Imm(False
, 32)));
1055 /* And finally do the shift. */
1056 addInstr(env
, MIPSInstr_Shft(shftOp
, True
/*32bit shift */,
1057 r_dst
, r_srcL_se
, ri_srcR
));
1059 addInstr(env
, MIPSInstr_Shft(shftOp
, True
/*32bit shift */,
1060 r_dst
, r_srcL
, ri_srcR
));
1061 } else if (ty
== Ity_I64
) {
1063 addInstr(env
, MIPSInstr_Shft(shftOp
, False
/*64bit shift */,
1064 r_dst
, r_srcL
, ri_srcR
));
1070 if (!mode64
&& (e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
1071 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
)) {
1072 HReg tmp1
, tmp2
, tmp3
, tmp4
;
1073 HReg dst1
= newVRegI(env
);
1074 HReg dst2
= newVRegI(env
);
1075 iselInt64Expr(&tmp1
, &tmp2
, env
, e
->Iex
.Binop
.arg1
);
1076 iselInt64Expr(&tmp3
, &tmp4
, env
, e
->Iex
.Binop
.arg2
);
1077 addInstr(env
, MIPSInstr_Cmp(False
, True
, dst1
, tmp1
, tmp3
, MIPScc_EQ
));
1078 addInstr(env
, MIPSInstr_Cmp(False
, True
, dst2
, tmp2
, tmp4
, MIPScc_EQ
));
1079 addInstr(env
, MIPSInstr_Alu(Malu_AND
, dst1
, dst1
, MIPSRH_Reg(dst2
)));
1083 /* Cmp*32*(x,y) ? */
1084 if (e
->Iex
.Binop
.op
== Iop_CmpEQ32
1085 || e
->Iex
.Binop
.op
== Iop_CmpEQ8
1086 || e
->Iex
.Binop
.op
== Iop_CmpEQ16
1087 || e
->Iex
.Binop
.op
== Iop_CmpNE32
1088 || e
->Iex
.Binop
.op
== Iop_CmpNE64
1089 || e
->Iex
.Binop
.op
== Iop_CmpLT32S
1090 || e
->Iex
.Binop
.op
== Iop_CmpLT32U
1091 || e
->Iex
.Binop
.op
== Iop_CmpLT64U
1092 || e
->Iex
.Binop
.op
== Iop_CmpLE32U
1093 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
1094 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
1095 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
1096 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
1097 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ32
1098 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
) {
1100 Bool syned
= (e
->Iex
.Binop
.op
== Iop_CmpLT32S
1101 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
1102 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
1103 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
);
1105 HReg dst
= newVRegI(env
);
1106 HReg r1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1107 HReg r2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1111 switch (e
->Iex
.Binop
.op
) {
1113 case Iop_CasCmpEQ32
:
1159 case Iop_CasCmpEQ64
:
1164 vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
1167 addInstr(env
, MIPSInstr_Cmp(syned
, size32
, dst
, r1
, r2
, cc
));
1171 if (e
->Iex
.Binop
.op
== Iop_Max32U
) {
1172 HReg tmp
= newVRegI(env
);
1173 HReg r_dst
= newVRegI(env
);
1174 HReg argL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1175 HReg argR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1176 MIPSRH
*argRH
= MIPSRH_Reg(argR
);
1182 addInstr(env
, MIPSInstr_Alu(Malu_SLT
, tmp
, argL
, argRH
));
1183 #if (__mips_isa_rev >= 6)
1185 HReg r_temp
= newVRegI(env
);
1186 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dst
, argL
, tmp
));
1187 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, argR
, tmp
));
1188 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
1189 MIPSRH_Reg(r_temp
)));
1193 addInstr(env
, mk_iMOVds_RR(r_dst
, argL
));
1194 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dst
, argR
, tmp
));
1199 if (e
->Iex
.Binop
.op
== Iop_Mul32
) {
1200 HReg r_dst
= newVRegI(env
);
1201 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1202 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1203 #if (__mips_isa_rev >= 6)
1204 addInstr(env
, MIPSInstr_Mulr6(False
, True
, True
,
1205 r_dst
, r_srcL
, r_srcR
));
1207 addInstr(env
, MIPSInstr_Mul(r_dst
, r_srcL
, r_srcR
));
1212 if (e
->Iex
.Binop
.op
== Iop_Mul64
||
1213 e
->Iex
.Binop
.op
== Iop_MullS32
) {
1215 HReg r_dst
= newVRegI(env
);
1216 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1217 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1218 #if (__mips_isa_rev >= 6)
1219 addInstr(env
, MIPSInstr_Mulr6(False
, False
, True
,
1220 r_dst
, r_srcL
, r_srcR
));
1222 addInstr(env
, MIPSInstr_Mult(True
, r_srcL
, r_srcR
));
1223 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1228 if (e
->Iex
.Binop
.op
== Iop_MullU32
) {
1230 HReg r_tmpL
= newVRegI(env
);
1231 HReg r_tmpR
= newVRegI(env
);
1232 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1233 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1234 #if (__mips_isa_rev >= 6)
1235 addInstr(env
, MIPSInstr_Ext(r_tmpL
, r_srcL
, 0, 32));
1236 addInstr(env
, MIPSInstr_Ext(r_tmpR
, r_srcR
, 0, 32));
1237 addInstr(env
, MIPSInstr_Mulr6(True
, False
, True
,
1238 r_tmpR
, r_tmpL
, r_tmpR
));
1240 if (VEX_MIPS_CPU_HAS_MIPS64R2(hwcaps_host
)) {
1241 addInstr(env
, MIPSInstr_Ext(r_tmpL
, r_srcL
, 0, 32));
1242 addInstr(env
, MIPSInstr_Ext(r_tmpR
, r_srcR
, 0, 32));
1244 addInstr(env
, MIPSInstr_LI(r_tmpL
, 0xFFFFFFFF));
1245 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_tmpR
, r_srcR
,
1246 MIPSRH_Reg(r_tmpL
)));
1247 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_tmpL
, r_srcL
,
1248 MIPSRH_Reg(r_tmpL
)));
1250 addInstr(env
, MIPSInstr_Mult(False
, r_tmpL
, r_tmpR
));
1251 addInstr(env
, MIPSInstr_Mflo(r_tmpR
));
1256 if (e
->Iex
.Binop
.op
== Iop_MullU8
||
1257 e
->Iex
.Binop
.op
== Iop_MullS8
||
1258 e
->Iex
.Binop
.op
== Iop_MullU16
||
1259 e
->Iex
.Binop
.op
== Iop_MullS16
) {
1260 Bool syned
= toBool((e
->Iex
.Binop
.op
== Iop_MullS8
) ||
1261 (e
->Iex
.Binop
.op
== Iop_MullS16
));
1262 HReg r_dst
= newVRegI(env
);
1263 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1264 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1265 #if (__mips_isa_rev >= 6)
1267 Int no_bits
= (e
->Iex
.Binop
.op
== Iop_MullS16
) ? 16 : 24;
1268 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1270 MIPSRH_Imm(False
, no_bits
)));
1271 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1273 MIPSRH_Imm(False
, no_bits
)));
1274 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1276 MIPSRH_Imm(False
, no_bits
)));
1277 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1279 MIPSRH_Imm(False
, no_bits
)));
1281 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, True
,
1282 r_dst
, r_srcL
, r_srcR
));
1285 Int no_bits
= (e
->Iex
.Binop
.op
== Iop_MullS16
) ? 16 : 24;
1286 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1288 MIPSRH_Imm(False
, no_bits
)));
1289 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1291 MIPSRH_Imm(False
, no_bits
)));
1292 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
,
1294 MIPSRH_Imm(False
, no_bits
)));
1295 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
,
1297 MIPSRH_Imm(False
, no_bits
)));
1298 addInstr(env
, MIPSInstr_Mul(r_dst
, r_srcL
, r_srcR
));
1301 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
1302 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1308 if (e
->Iex
.Binop
.op
== Iop_CmpF64
) {
1309 HReg r_srcL
, r_srcR
;
1311 r_srcL
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
1312 r_srcR
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1314 r_srcL
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
1315 r_srcR
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1317 #if (__mips_isa_rev >= 6)
1318 HReg tmp
= newVRegI(env
);
1320 HReg result
= newVRegI(env
);
1321 if (mode64
) tmpf
= newVRegF(env
);
1322 else tmpf
= newVRegD(env
);
1323 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN
, tmpf
, r_srcL
, r_srcR
));
1324 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1325 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1326 MIPSRH_Imm(False
, 0x45)));
1327 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
,
1328 hregMIPS_GPR0(env
->mode64
),
1330 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT
, tmpf
, r_srcL
, r_srcR
));
1331 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1332 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1333 MIPSRH_Imm(False
, 0x1)));
1334 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1336 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ
, tmpf
, r_srcL
, r_srcR
));
1337 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1338 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1339 MIPSRH_Imm(False
, 0x40)));
1340 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1344 HReg tmp
= newVRegI(env
);
1345 HReg r_ccMIPS
= newVRegI(env
);
1346 HReg r_ccIR
= newVRegI(env
);
1347 HReg r_ccIR_b0
= newVRegI(env
);
1348 HReg r_ccIR_b2
= newVRegI(env
);
1349 HReg r_ccIR_b6
= newVRegI(env
);
1351 /* Create in dst, the IRCmpF64Result encoded result. */
1353 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ
, tmp
, r_srcL
, r_srcR
));
1354 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccMIPS
, tmp
,
1355 MIPSRH_Imm(False
, 1)));
1357 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN
, tmp
, r_srcL
, r_srcR
));
1358 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1361 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT
, tmp
, r_srcL
, r_srcR
));
1362 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
,
1363 tmp
, MIPSRH_Imm(False
, 2)));
1364 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1367 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_NGT
,
1368 tmp
, r_srcL
, r_srcR
));
1369 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, tmp
,
1370 MIPSRH_Imm(False
, 3)));
1372 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tmp
, tmp
, MIPSRH_Reg(tmp
)));
1373 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1374 MIPSRH_Imm(False
, 8)));
1375 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccMIPS
, r_ccMIPS
,
1377 /* Map compare result from MIPS to IR,
1378 conforming to CmpF64 definition.
1379 FP cmp result | MIPS | IR
1380 --------------------------
1387 /* r_ccIR_b0 = r_ccMIPS[0] | r_ccMIPS[3] */
1388 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
, r_ccIR_b0
, r_ccMIPS
,
1389 MIPSRH_Imm(False
, 0x3)));
1390 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR_b0
, r_ccMIPS
,
1391 MIPSRH_Reg(r_ccIR_b0
)));
1392 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b0
, r_ccIR_b0
,
1393 MIPSRH_Imm(False
, 0x1)));
1395 /* r_ccIR_b2 = r_ccMIPS[0] */
1396 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccIR_b2
, r_ccMIPS
,
1397 MIPSRH_Imm(False
, 0x2)));
1398 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b2
, r_ccIR_b2
,
1399 MIPSRH_Imm(False
, 0x4)));
1401 /* r_ccIR_b6 = r_ccMIPS[0] | r_ccMIPS[1] */
1402 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
, r_ccIR_b6
,
1403 r_ccMIPS
, MIPSRH_Imm(False
, 0x1)));
1404 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR_b6
, r_ccMIPS
,
1405 MIPSRH_Reg(r_ccIR_b6
)));
1406 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_ccIR_b6
, r_ccIR_b6
,
1407 MIPSRH_Imm(False
, 0x6)));
1408 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_ccIR_b6
, r_ccIR_b6
,
1409 MIPSRH_Imm(False
, 0x40)));
1411 /* r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 */
1412 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR
, r_ccIR_b0
,
1413 MIPSRH_Reg(r_ccIR_b2
)));
1414 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_ccIR
, r_ccIR
,
1415 MIPSRH_Reg(r_ccIR_b6
)));
1420 if (e
->Iex
.Binop
.op
== Iop_CmpF32
) {
1421 #if (__mips_isa_rev >= 6)
1422 HReg r_srcL
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
1423 HReg r_srcR
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1424 HReg tmp
= newVRegI(env
);
1426 HReg result
= newVRegI(env
);
1427 if (mode64
) tmpf
= newVRegF(env
);
1428 else tmpf
= newVRegD(env
);
1429 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_UN_S
, tmpf
, r_srcL
, r_srcR
));
1430 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1431 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1432 MIPSRH_Imm(False
, 0x45)));
1433 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
,
1434 hregMIPS_GPR0(env
->mode64
),
1436 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_LT_S
, tmpf
, r_srcL
, r_srcR
));
1437 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1438 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1439 MIPSRH_Imm(False
, 0x1)));
1440 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1442 addInstr(env
, MIPSInstr_FpCompare(Mfp_CMP_EQ_S
, tmpf
, r_srcL
, r_srcR
));
1443 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, tmp
, tmpf
));
1444 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, tmp
,
1445 MIPSRH_Imm(False
, 0x40)));
1446 addInstr(env
, MIPSInstr_Alu(Malu_OR
, result
, result
,
1452 if (e
->Iex
.Binop
.op
== Iop_DivModU32to32
||
1453 e
->Iex
.Binop
.op
== Iop_DivModS32to32
) {
1454 HReg tLo
= newVRegI(env
);
1455 HReg tHi
= newVRegI(env
);
1456 HReg mask
= newVRegI(env
);
1457 HReg tLo_1
= newVRegI(env
);
1458 HReg tHi_1
= newVRegI(env
);
1459 HReg r_dst
= newVRegI(env
);
1460 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS32to32
);
1462 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1463 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1464 #if (__mips_isa_rev >= 6)
1465 addInstr(env
, MIPSInstr_Divr6(syned
/* Unsigned or Signed */ ,
1466 True
/* 32bit or 64bit div */ ,
1468 tLo
, r_srcL
, r_srcR
));
1469 addInstr(env
, MIPSInstr_Divr6(syned
/* Unsigned or Signed */ ,
1470 True
/*3 2bit or 64bit div */ ,
1472 tHi
, r_srcL
, r_srcR
));
1474 addInstr(env
, MIPSInstr_Div(syned
, True
, r_srcL
, r_srcR
));
1475 addInstr(env
, MIPSInstr_Mfhi(tHi
));
1476 addInstr(env
, MIPSInstr_Mflo(tLo
));
1478 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tHi_1
, tHi
,
1479 MIPSRH_Imm(False
, 32)));
1481 addInstr(env
, MIPSInstr_LI(mask
, 0xffffffff));
1482 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1485 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1486 MIPSRH_Reg(tLo_1
)));
1491 if (e
->Iex
.Binop
.op
== Iop_DivS32
||
1492 e
->Iex
.Binop
.op
== Iop_DivU32
||
1493 (e
->Iex
.Binop
.op
== Iop_DivS64
&& mode64
) ||
1494 (e
->Iex
.Binop
.op
== Iop_DivU64
&& mode64
)) {
1495 HReg r_dst
= newVRegI(env
);
1496 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivS32
||
1497 e
->Iex
.Binop
.op
== Iop_DivS64
);
1498 Bool div32
= toBool(e
->Iex
.Binop
.op
== Iop_DivS32
||
1499 e
->Iex
.Binop
.op
== Iop_DivU32
);
1500 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1501 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1502 #if (__mips_isa_rev >= 6)
1503 addInstr(env
, MIPSInstr_Divr6(syned
, div32
, False
,
1504 r_dst
, r_srcL
, r_srcR
));
1506 addInstr(env
, MIPSInstr_Div(syned
, div32
, r_srcL
, r_srcR
));
1507 addInstr(env
, MIPSInstr_Mflo(r_dst
));
1512 if (e
->Iex
.Binop
.op
== Iop_8HLto16
1513 || e
->Iex
.Binop
.op
== Iop_16HLto32
) {
1514 HReg tHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1515 HReg tLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1516 HReg tLo_1
= newVRegI(env
);
1517 HReg tHi_1
= newVRegI(env
);
1518 HReg r_dst
= newVRegI(env
);
1521 switch (e
->Iex
.Binop
.op
) {
1534 /* sll tHi_1, tHi, shift
1535 and tLo_1, tLo, mask
1536 or r_dst, tHi_1, tLo_1 */
1537 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tHi_1
, tHi
,
1538 MIPSRH_Imm(False
, shift
)));
1539 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1540 MIPSRH_Imm(False
, mask
)));
1541 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1542 MIPSRH_Reg(tLo_1
)));
1546 if (e
->Iex
.Binop
.op
== Iop_32HLto64
) {
1548 HReg tHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1549 HReg tLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1550 HReg tLo_1
= newVRegI(env
);
1551 HReg tHi_1
= newVRegI(env
);
1552 HReg r_dst
= newVRegI(env
);
1553 HReg mask
= newVRegI(env
);
1555 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
, tHi_1
, tHi
,
1556 MIPSRH_Imm(False
, 32)));
1558 addInstr(env
, MIPSInstr_LI(mask
, 0xffffffff));
1559 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo_1
, tLo
,
1561 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, tHi_1
,
1562 MIPSRH_Reg(tLo_1
)));
1567 if (e
->Iex
.Binop
.op
== Iop_F32toI64S
) {
1569 HReg valS
= newVRegI(env
);
1570 HReg tmpF
= newVRegF(env
);
1571 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1573 /* CVTLS tmpF, valF */
1574 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1575 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpF
, valF
));
1576 set_MIPS_rounding_default(env
);
1578 /* Doubleword Move from Floating Point
1580 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, valS
, tmpF
));
1585 if (e
->Iex
.Binop
.op
== Iop_F64toI64S
) {
1587 HReg valS
= newVRegI(env
);
1588 HReg tmpF
= newVRegF(env
);
1589 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1591 /* CVTLS tmpF, valF */
1592 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1593 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, tmpF
, valF
));
1594 set_MIPS_rounding_default(env
);
1596 /* Doubleword Move from Floating Point
1598 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, valS
, tmpF
));
1603 if (e
->Iex
.Binop
.op
== Iop_F64toI32S
) {
1606 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1608 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1609 HReg valS
= newVRegF(env
);
1610 HReg r_dst
= newVRegI(env
);
1612 /* CVTWD valS, valD */
1613 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1614 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWD
, valS
, valD
));
1615 set_MIPS_rounding_default(env
);
1617 /* Move Word From Floating Point
1619 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1624 if (e
->Iex
.Binop
.op
== Iop_F32toI32U
) {
1625 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1626 HReg tmpD
= newVRegD(env
);
1627 HReg r_dst
= newVRegI(env
);
1630 /* CVTLS tmpD, valF */
1631 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1632 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpD
, valF
));
1633 set_MIPS_rounding_default(env
);
1635 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
1636 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
1639 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
1642 #if defined (_MIPSEL)
1643 addInstr(env
, MIPSInstr_Load(4, r_dst
, am_addr
, mode64
));
1644 #elif defined (_MIPSEB)
1645 addInstr(env
, MIPSInstr_Load(4, r_dst
, nextMIPSAModeFloat(am_addr
),
1655 if (e
->Iex
.Binop
.op
== Iop_F64toI64U
) {
1657 HReg tmp
= newVRegV(env
);
1659 r_src
= iselFltExpr( env
, e
->Iex
.Binop
.arg2
);
1660 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
1661 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_U
, MSA_F_DW
, tmp
, r_src
));
1662 HReg r_dst
= newVRegI(env
);
1664 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dst
, MSA_DFN_D
| 0));
1665 set_MIPS_rounding_default_MSA(env
);
1669 if (e
->Iex
.Binop
.op
== Iop_GetElem8x16
) {
1670 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1671 HReg r_dst
= newVRegI(env
);
1672 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1677 MIPSInstr_MsaElm(MSA_COPY_U
, v_src
, r_dst
,
1679 (tmp
->Mrh
.Imm
.imm16
& 0x0f)));
1683 HReg v_tmp
= newVRegV(env
);
1685 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_B
, v_tmp
, v_src
,
1688 MIPSInstr_MsaElm(MSA_COPY_U
, v_tmp
, r_dst
,
1698 if (e
->Iex
.Binop
.op
== Iop_GetElem16x8
) {
1699 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1700 HReg r_dst
= newVRegI(env
);
1701 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1706 MIPSInstr_MsaElm(MSA_COPY_U
, v_src
, r_dst
,
1708 (tmp
->Mrh
.Imm
.imm16
& 0x07)));
1712 HReg v_tmp
= newVRegV(env
);
1714 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_H
, v_tmp
, v_src
,
1717 MIPSInstr_MsaElm(MSA_COPY_U
, v_tmp
, r_dst
,
1726 if (e
->Iex
.Binop
.op
== Iop_GetElem32x4
) {
1727 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1728 HReg r_dst
= newVRegI(env
);
1729 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1733 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dst
,
1735 (tmp
->Mrh
.Imm
.imm16
& 0x03)));
1739 HReg v_tmp
= newVRegV(env
);
1741 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_W
, v_tmp
, v_src
,
1744 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dst
,
1752 if (e
->Iex
.Binop
.op
== Iop_GetElem64x2
) {
1754 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
1755 HReg r_dst
= newVRegI(env
);
1756 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
1761 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dst
,
1763 (tmp
->Mrh
.Imm
.imm16
& 0x01)));
1767 HReg v_tmp
= newVRegV(env
);
1769 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_D
, v_tmp
, v_src
,
1772 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dst
,
1781 if (e
->Iex
.Binop
.op
== Iop_F32toI32S
) {
1782 HReg valS
= newVRegF(env
);
1783 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1784 HReg r_dst
= newVRegI(env
);
1786 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1787 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWS
, valS
, valF
));
1788 set_MIPS_rounding_default(env
);
1790 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1795 /* -------- DSP ASE -------- */
1796 /* All used cases involving host-side helper calls. */
1798 switch (e
->Iex
.Binop
.op
) {
1800 fn
= &h_generic_calc_HAdd8Ux4
; break;
1802 fn
= &h_generic_calc_HSub8Ux4
; break;
1804 fn
= &h_generic_calc_HSub16Sx2
; break;
1806 fn
= &h_generic_calc_QSub8Ux4
; break;
1811 /* What's the retloc? */
1812 RetLoc rloc
= mk_RetLoc_INVALID();
1813 if (ty
== Ity_I32
) {
1814 rloc
= mk_RetLoc_simple(RLPri_Int
);
1816 else if (ty
== Ity_I64
) {
1817 rloc
= mode64
? mk_RetLoc_simple(RLPri_Int
) :
1818 mk_RetLoc_simple(RLPri_2Int
);
1825 HReg regL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
1826 HReg regR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
1827 HReg res
= newVRegI(env
);
1828 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR4(env
->mode64
), regL
));
1829 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR5(env
->mode64
), regR
));
1830 argiregs
|= (1 << 4);
1831 argiregs
|= (1 << 5);
1832 addInstr(env
, MIPSInstr_CallAlways( MIPScc_AL
,
1835 addInstr(env
, mk_iMOVds_RR(res
, hregMIPS_GPR2(env
->mode64
)));
1841 /* --------- UNARY OP --------- */
1843 IROp op_unop
= e
->Iex
.Unop
.op
;
1855 HReg r_dst
= newVRegI(env
);
1856 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1900 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, sz32
, r_dst
, r_src
,
1901 MIPSRH_Imm(False
, amt
)));
1902 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, sz32
, r_dst
, r_dst
,
1903 MIPSRH_Imm(False
, amt
)));
1907 /* not(x) = nor(x,x) */
1909 HReg r_dst
= newVRegI(env
);
1910 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1911 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
1913 addInstr(env
, MIPSInstr_LI(r_dst
, 0x1));
1914 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, r_dst
, r_srcR
));
1922 HReg r_dst
= newVRegI(env
);
1923 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1924 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
1926 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dst
, r_srcL
, r_srcR
));
1930 case Iop_ReinterpF32asI32
: {
1931 HReg fr_src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
1932 HReg r_dst
= newVRegI(env
);
1934 /* Move Word From Floating Point
1935 mfc1 r_dst, fr_src */
1936 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, fr_src
));
1941 case Iop_ReinterpF64asI64
: {
1943 HReg fr_src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
1944 HReg r_dst
= newVRegI(env
);
1946 /* Doubleword Move from Floating Point
1947 mfc1 r_dst, fr_src */
1948 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmfc1
, r_dst
, fr_src
));
1953 case Iop_F64toI32S
: {
1956 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
1958 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
1959 HReg valS
= newVRegF(env
);
1960 HReg r_dst
= newVRegI(env
);
1962 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
1963 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWD
, valS
, valD
));
1964 set_MIPS_rounding_default(env
);
1966 /* Move Word From Floating Point
1968 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mfc1
, r_dst
, valS
));
1977 return iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1979 case Iop_32HIto16
: {
1980 HReg r_dst
= newVRegI(env
);
1981 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1982 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
1983 r_dst
, r_src
, MIPSRH_Imm(False
, 16)));
1990 UShort mask
= (op_unop
== Iop_64to1
) ? 0x1 : 0xFF;
1991 r_dst
= newVRegI(env
);
1993 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
1996 iselInt64Expr(&tmp
, &r_src
, env
, e
->Iex
.Unop
.arg
);
1998 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_dst
, r_src
,
1999 MIPSRH_Imm(False
, mask
)));
2004 HReg r_dst
= newVRegI(env
);
2005 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2006 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
2007 r_dst
, r_src
, MIPSRH_Imm(False
, 8)));
2019 HReg r_dst
= newVRegI(env
);
2020 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2028 mask
= toUShort(0x1);
2035 mask
= toUShort(0xFF);
2041 mask
= toUShort(0xFFFF);
2047 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_dst
, r_src
,
2048 MIPSRH_Imm(False
, mask
)));
2053 HReg r_dst
= newVRegI(env
);
2054 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2056 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, False
/*!32bit shift */,
2057 r_dst
, r_src
, MIPSRH_Imm(False
, 32)));
2058 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, False
/*!32bit shift */,
2059 r_dst
, r_dst
, MIPSRH_Imm(False
, 32)));
2063 case Iop_64HIto32
: {
2065 HReg r_dst
= newVRegI(env
);
2066 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2067 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
/*64bit shift */,
2068 r_dst
, r_src
, MIPSRH_Imm(True
, 32)));
2072 iselInt64Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2079 HReg r_dst
= newVRegI(env
);
2080 r_dst
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2084 iselInt64Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2090 vassert(env
->mode64
);
2091 HReg r_dst
= newVRegI(env
);
2092 r_dst
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2097 HReg r_dst
= newVRegI(env
);
2098 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2100 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/*!32bit shift */,
2101 r_dst
, r_src
, MIPSRH_Imm(True
, 0)));
2106 case Iop_CmpNEZ16
: {
2107 HReg r_dst
= newVRegI(env
);
2108 HReg tmp
= newVRegI(env
);
2109 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2110 UShort mask
= (op_unop
== Iop_CmpNEZ8
) ? 0xFF : 0xFFFF;
2112 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tmp
, r_src
,
2113 MIPSRH_Imm(False
, mask
)));
2114 addInstr(env
, MIPSInstr_Cmp(False
, True
, r_dst
, tmp
,
2115 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2119 case Iop_CmpNEZ32
: {
2120 HReg r_dst
= newVRegI(env
);
2121 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2123 addInstr(env
, MIPSInstr_Cmp(False
, True
, r_dst
, r_src
,
2124 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2128 case Iop_CmpwNEZ32
: {
2129 HReg r_dst
= newVRegI(env
);
2130 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2132 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, hregMIPS_GPR0(mode64
),
2133 MIPSRH_Reg(r_src
)));
2135 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2136 MIPSRH_Reg(r_src
)));
2137 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, r_dst
, r_dst
,
2138 MIPSRH_Imm(False
, 31)));
2146 if (op_unop
== Iop_Left64
&& !mode64
)
2148 HReg r_dst
= newVRegI(env
);
2149 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2150 MIPSAluOp op
= (op_unop
== Iop_Left64
) ? Malu_DSUB
: Malu_SUB
;
2151 addInstr(env
, MIPSInstr_Alu(op
, r_dst
,
2152 hregMIPS_GPR0(mode64
),
2153 MIPSRH_Reg(r_src
)));
2154 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2155 MIPSRH_Reg(r_src
)));
2163 HReg r_dst
= newVRegI(env
);
2164 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2165 MIPSUnaryOp op
= (op_unop
== Iop_Clz64
) ? Mun_DCLZ
: Mun_CLZ
;
2166 addInstr(env
, MIPSInstr_Unary(op
, r_dst
, r_src
));
2170 case Iop_CmpNEZ64
: {
2172 HReg r_dst
= newVRegI(env
);
2175 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2177 r_src
= newVRegI(env
);
2178 iselInt64Expr(&hi
, &lo
, env
, e
->Iex
.Unop
.arg
);
2179 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_src
, lo
, MIPSRH_Reg(hi
)));
2181 addInstr(env
, MIPSInstr_Cmp(False
, !(env
->mode64
), r_dst
, r_src
,
2182 hregMIPS_GPR0(mode64
), MIPScc_NE
));
2186 case Iop_CmpwNEZ64
: {
2188 HReg tmp2
= newVRegI(env
);
2189 vassert(env
->mode64
);
2190 tmp1
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2192 addInstr(env
, MIPSInstr_Alu(Malu_DSUB
, tmp2
, hregMIPS_GPR0(mode64
),
2195 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp2
, tmp2
, MIPSRH_Reg(tmp1
)));
2196 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, False
, tmp2
, tmp2
,
2197 MIPSRH_Imm (False
, 63)));
2201 case Iop_128HIto64
: {
2204 iselInt128Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2205 return rHi
; /* and abandon rLo .. poor wee thing :-) */
2211 iselInt128Expr(&rHi
, &rLo
, env
, e
->Iex
.Unop
.arg
);
2212 return rLo
; /* and abandon rLo .. poor wee thing :-) */
2215 case Iop_V128to32
: {
2216 HReg i_dst
= newVRegI(env
);
2217 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2220 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, i_dst
, MSA_DFN_W
));
2224 case Iop_V128HIto64
: {
2227 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2228 HReg reg
= newVRegI(env
);
2230 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 1));
2234 case Iop_V128to64
: {
2237 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2238 HReg reg
= newVRegI(env
);
2240 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 0));
2244 case Iop_F32toF16x4_DEP
: {
2247 HReg v_arg
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2248 HReg v_src
= newVRegV(env
);
2249 set_guest_MIPS_rounding_mode_MSA(env
);
2251 MIPSInstr_Msa3RF(MSA_FEXDO
, MSA_F_WH
,
2252 v_src
, v_arg
, v_arg
));
2253 set_MIPS_rounding_default_MSA(env
);
2254 HReg reg
= newVRegI(env
);
2256 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, reg
, MSA_DFN_D
| 0));
2265 /* -------- DSP ASE -------- */
2266 /* All Unop cases involving host-side helper calls. */
2268 switch (e
->Iex
.Unop
.op
) {
2269 case Iop_CmpNEZ16x2
:
2270 fn
= &h_generic_calc_CmpNEZ16x2
; break;
2272 fn
= &h_generic_calc_CmpNEZ8x4
; break;
2277 RetLoc rloc
= mk_RetLoc_INVALID();
2278 if (ty
== Ity_I32
) {
2279 rloc
= mk_RetLoc_simple(RLPri_Int
);
2281 else if (ty
== Ity_I64
) {
2282 rloc
= mode64
? mk_RetLoc_simple(RLPri_Int
) :
2283 mk_RetLoc_simple(RLPri_2Int
);
2290 HReg regL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2291 HReg res
= newVRegI(env
);
2292 addInstr(env
, mk_iMOVds_RR(hregMIPS_GPR4(env
->mode64
), regL
));
2293 argiregs
|= (1 << 4);
2294 addInstr(env
, MIPSInstr_CallAlways( MIPScc_AL
,
2297 addInstr(env
, mk_iMOVds_RR(res
, hregMIPS_GPR2(env
->mode64
)));
2304 /* --------- GET --------- */
2306 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
2307 || ((ty
== Ity_I64
) && mode64
)) {
2308 HReg r_dst
= newVRegI(env
);
2310 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
2311 GuestStatePointer(mode64
));
2312 addInstr(env
, MIPSInstr_Load(toUChar(sizeofIRType(ty
)), r_dst
, am_addr
,
2319 /* --------- ITE --------- */
2321 if ((ty
== Ity_I8
|| ty
== Ity_I16
||
2322 ty
== Ity_I32
|| ((ty
== Ity_I64
))) &&
2323 typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
) {
2324 HReg r0
= iselWordExpr_R(env
, e
->Iex
.ITE
.iffalse
);
2325 HReg r1
= iselWordExpr_R(env
, e
->Iex
.ITE
.iftrue
);
2326 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
2327 HReg r_dst
= newVRegI(env
);
2330 * movn r_dst, r1, r_cond
2332 #if (__mips_isa_rev >= 6)
2333 HReg r_temp
= newVRegI(env
);
2334 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dst
, r0
, r_cond
));
2335 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, r1
, r_cond
));
2336 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dst
, r_dst
,
2337 MIPSRH_Reg(r_temp
)));
2340 addInstr(env
, mk_iMOVds_RR(r_dst
, r0
));
2341 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dst
, r1
, r_cond
));
2348 /* --------- LITERAL --------- */
2349 /* 32/16/8-bit literals */
2352 HReg r_dst
= newVRegI(env
);
2353 IRConst
*con
= e
->Iex
.Const
.con
;
2358 l
= (Long
) con
->Ico
.U64
;
2361 l
= (Long
) (Int
) con
->Ico
.U32
;
2364 l
= (Long
) (Int
) (Short
) con
->Ico
.U16
;
2367 l
= (Long
) (Int
) (Char
) con
->Ico
.U8
;
2370 vpanic("iselIntExpr_R.const(mips)");
2372 addInstr(env
, MIPSInstr_LI(r_dst
, (ULong
) l
));
2376 /* --------- CCALL --------- */
2378 HReg r_dst
= newVRegI(env
);
2379 vassert(ty
== e
->Iex
.CCall
.retty
);
2381 /* be very restrictive for now. Only 32/64-bit ints allowed for
2382 args, and 64 and 32 bits for return type. Don't forget to change
2383 the RetLoc if more return types are allowed in future. */
2384 if (e
->Iex
.CCall
.retty
!= Ity_I64
&& e
->Iex
.CCall
.retty
!= Ity_I32
)
2387 /* Marshal args, do the call, clear stack. */
2389 RetLoc rloc
= mk_RetLoc_INVALID();
2390 doHelperCall(&addToSp
, &rloc
, env
, NULL
/*guard*/, e
->Iex
.CCall
.cee
,
2391 e
->Iex
.CCall
.retty
, e
->Iex
.CCall
.args
);
2393 vassert(is_sane_RetLoc(rloc
));
2394 vassert(rloc
.pri
== RLPri_Int
);
2395 vassert(addToSp
== 0);
2396 addInstr(env
, mk_iMOVds_RR(r_dst
, hregMIPS_GPR2(mode64
)));
2400 #if (__mips_isa_rev >= 6)
2402 HReg dst
= newVRegI(env
);
2403 HReg src1
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg1
);
2404 HReg src2
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg2
);
2405 HReg src3
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg3
);
2406 HReg src4
= iselWordExpr_R(env
, e
->Iex
.Qop
.details
->arg4
);
2407 switch (e
->Iex
.Qop
.details
->op
) {
2409 addInstr(env
, MIPSInstr_Bitswap(Rotx32
, dst
, src1
, src2
, src3
, src4
));
2412 addInstr(env
, MIPSInstr_Bitswap(Rotx64
, dst
, src1
, src2
, src3
, src4
));
2423 } /* end switch(e->tag) */
2425 /* We get here if no pattern matched. */
2427 vex_printf("--------------->\n");
2428 if (e
->tag
== Iex_RdTmp
)
2429 vex_printf("Iex_RdTmp \n");
2432 vpanic("iselWordExpr_R(mips): cannot reduce tree");
2435 /* --------------------- RH --------------------- */
2437 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2438 (reg-or-halfword-immediate). It's important to specify whether the
2439 immediate is to be regarded as signed or not. If yes, this will
2440 never return -32768 as an immediate; this guaranteed that all
2441 signed immediates that are return can have their sign inverted if
2444 static MIPSRH
*iselWordExpr_RH(ISelEnv
* env
, Bool syned
, IRExpr
* e
)
2446 MIPSRH
*ri
= iselWordExpr_RH_wrk(env
, syned
, e
);
2447 /* sanity checks ... */
2450 vassert(ri
->Mrh
.Imm
.syned
== syned
);
2452 vassert(ri
->Mrh
.Imm
.imm16
!= 0x8000);
2455 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2456 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2459 vpanic("iselIntExpr_RH: unknown mips RH tag");
2463 /* DO NOT CALL THIS DIRECTLY ! */
2464 static MIPSRH
*iselWordExpr_RH_wrk(ISelEnv
* env
, Bool syned
, IRExpr
* e
)
2468 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2469 vassert(ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
||
2470 ((ty
== Ity_I64
) && env
->mode64
));
2472 /* special case: immediate */
2473 if (e
->tag
== Iex_Const
) {
2474 IRConst
*con
= e
->Iex
.Const
.con
;
2475 /* What value are we aiming to generate? */
2477 /* Note: Not sign-extending - we carry 'syned' around */
2479 vassert(env
->mode64
);
2483 u
= 0xFFFFFFFF & con
->Ico
.U32
;
2486 u
= 0x0000FFFF & con
->Ico
.U16
;
2489 u
= 0x000000FF & con
->Ico
.U8
;
2492 vpanic("iselIntExpr_RH.Iex_Const(mips)");
2495 /* Now figure out if it's representable. */
2496 if (!syned
&& u
<= 65535) {
2497 return MIPSRH_Imm(False
/*unsigned */ , toUShort(u
& 0xFFFF));
2499 if (syned
&& l
>= -32767 && l
<= 32767) {
2500 return MIPSRH_Imm(True
/*signed */ , toUShort(u
& 0xFFFF));
2502 /* no luck; use the Slow Way. */
2504 /* default case: calculate into a register and return that */
2505 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2508 /* --------------------- RH5u --------------------- */
2510 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2511 being an immediate in the range 1 .. 31 inclusive. Used for doing
2514 static MIPSRH
*iselWordExpr_RH5u(ISelEnv
* env
, IRExpr
* e
)
2517 ri
= iselWordExpr_RH5u_wrk(env
, e
);
2518 /* sanity checks ... */
2521 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 31);
2522 vassert(!ri
->Mrh
.Imm
.syned
);
2525 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcInt32
);
2526 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2529 vpanic("iselIntExpr_RH5u: unknown mips RH tag");
2533 /* DO NOT CALL THIS DIRECTLY ! */
2534 static MIPSRH
*iselWordExpr_RH5u_wrk(ISelEnv
* env
, IRExpr
* e
)
2536 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2537 vassert(ty
== Ity_I8
);
2539 /* special case: immediate */
2540 if (e
->tag
== Iex_Const
2541 && e
->Iex
.Const
.con
->tag
== Ico_U8
2542 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 31) {
2543 return MIPSRH_Imm(False
/*unsigned */ , e
->Iex
.Const
.con
->Ico
.U8
);
2546 /* default case: calculate into a register and return that */
2547 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2550 /* --------------------- RH6u --------------------- */
2552 static MIPSRH
*iselWordExpr_RH6u ( ISelEnv
* env
, IRExpr
* e
)
2555 ri
= iselWordExpr_RH6u_wrk(env
, e
);
2556 /* sanity checks ... */
2559 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 63);
2560 vassert(!ri
->Mrh
.Imm
.syned
);
2563 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2564 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2567 vpanic("iselIntExpr_RH6u: unknown RI tag");
2571 /* DO NOT CALL THIS DIRECTLY ! */
2572 static MIPSRH
*iselWordExpr_RH6u_wrk ( ISelEnv
* env
, IRExpr
* e
)
2574 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2575 vassert(ty
== Ity_I8
);
2577 /* special case: immediate */
2578 if (e
->tag
== Iex_Const
2579 && e
->Iex
.Const
.con
->tag
== Ico_U8
2580 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 63)
2582 return MIPSRH_Imm(False
/*unsigned */ ,
2583 e
->Iex
.Const
.con
->Ico
.U8
);
2586 /* default case: calculate into a register and return that */
2587 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2589 /* --------------------- RH7u --------------------- */
2591 static MIPSRH
*iselWordExpr_RH7u ( ISelEnv
* env
, IRExpr
* e
)
2594 ri
= iselWordExpr_RH7u_wrk(env
, e
);
2595 /* sanity checks ... */
2598 vassert(ri
->Mrh
.Imm
.imm16
>= 1 && ri
->Mrh
.Imm
.imm16
<= 127);
2599 vassert(!ri
->Mrh
.Imm
.syned
);
2602 vassert(hregClass(ri
->Mrh
.Reg
.reg
) == HRcGPR(env
->mode64
));
2603 vassert(hregIsVirtual(ri
->Mrh
.Reg
.reg
));
2606 vpanic("iselIntExpr_RH7u: unknown RI tag");
2610 /* DO NOT CALL THIS DIRECTLY ! */
2611 static MIPSRH
*iselWordExpr_RH7u_wrk ( ISelEnv
* env
, IRExpr
* e
)
2613 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2614 vassert(ty
== Ity_I8
);
2616 /* special case: immediate */
2617 if (e
->tag
== Iex_Const
2618 && e
->Iex
.Const
.con
->tag
== Ico_U8
2619 && e
->Iex
.Const
.con
->Ico
.U8
>= 1 && e
->Iex
.Const
.con
->Ico
.U8
<= 127)
2621 return MIPSRH_Imm(False
/*unsigned */ ,
2622 e
->Iex
.Const
.con
->Ico
.U8
);
2625 /* default case: calculate into a register and return that */
2626 return MIPSRH_Reg(iselWordExpr_R(env
, e
));
2630 /* --------------------- CONDCODE --------------------- */
2632 /* Generate code to evaluated a bit-typed expression, returning the
2633 condition code which would correspond when the expression would
2634 notionally have returned 1. */
2636 static MIPSCondCode
iselCondCode(ISelEnv
* env
, IRExpr
* e
)
2638 MIPSCondCode cc
= iselCondCode_wrk(env
,e
);
2639 vassert(cc
!= MIPScc_NV
);
2643 /* DO NOT CALL THIS DIRECTLY ! */
2644 static MIPSCondCode
iselCondCode_wrk(ISelEnv
* env
, IRExpr
* e
)
2647 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I1
);
2648 /* Cmp*32*(x,y) ? */
2649 if (e
->Iex
.Binop
.op
== Iop_CmpEQ32
2650 || e
->Iex
.Binop
.op
== Iop_CmpNE32
2651 || e
->Iex
.Binop
.op
== Iop_CmpNE64
2652 || e
->Iex
.Binop
.op
== Iop_CmpLT32S
2653 || e
->Iex
.Binop
.op
== Iop_CmpLT32U
2654 || e
->Iex
.Binop
.op
== Iop_CmpLT64U
2655 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
2656 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
2657 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
2658 || e
->Iex
.Binop
.op
== Iop_CmpEQ64
2659 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ32
2660 || e
->Iex
.Binop
.op
== Iop_CasCmpEQ64
) {
2662 Bool syned
= (e
->Iex
.Binop
.op
== Iop_CmpLT32S
2663 || e
->Iex
.Binop
.op
== Iop_CmpLE32S
2664 || e
->Iex
.Binop
.op
== Iop_CmpLT64S
2665 || e
->Iex
.Binop
.op
== Iop_CmpLE64S
);
2667 HReg dst
= newVRegI(env
);
2668 HReg r1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
2669 HReg r2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
2673 switch (e
->Iex
.Binop
.op
) {
2675 case Iop_CasCmpEQ32
:
2712 case Iop_CasCmpEQ64
:
2717 vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
2721 addInstr(env
, MIPSInstr_Cmp(syned
, size32
, dst
, r1
, r2
, cc
));
2722 /* Store result to guest_COND */
2723 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2725 addInstr(env
, MIPSInstr_Store(4,
2726 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2727 am_addr
->Mam
.IR
.base
),
2731 if (e
->Iex
.Binop
.op
== Iop_Not1
) {
2732 HReg r_dst
= newVRegI(env
);
2733 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
2734 MIPSRH
*r_srcR
= MIPSRH_Reg(r_srcL
);
2736 addInstr(env
, MIPSInstr_LI(r_dst
, 0x1));
2737 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, r_dst
, r_dst
, r_srcR
));
2738 /* Store result to guest_COND */
2739 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2741 addInstr(env
, MIPSInstr_Store(4,
2742 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2743 am_addr
->Mam
.IR
.base
),
2747 if (e
->tag
== Iex_RdTmp
|| e
->tag
== Iex_Unop
) {
2748 HReg r_dst
= iselWordExpr_R_wrk(env
, e
);
2749 /* Store result to guest_COND */
2750 MIPSAMode
*am_addr
= MIPSAMode_IR(0, GuestStatePointer(mode64
));
2752 addInstr(env
, MIPSInstr_Store(4,
2753 MIPSAMode_IR(am_addr
->Mam
.IR
.index
+ COND_OFFSET(mode64
),
2754 am_addr
->Mam
.IR
.base
),
2759 vex_printf("iselCondCode(mips): No such tag(%u)\n", e
->tag
);
2761 vpanic("iselCondCode(mips)");
2764 /*---------------------------------------------------------*/
2765 /*--- ISEL: Vector expressions (128 bit - SIMD) ---*/
2766 /*---------------------------------------------------------*/
2768 /* Compute a vector value into vector register. */
2769 static HReg
iselV128Expr (ISelEnv
* env
, IRExpr
* e
) {
2771 HReg r
= iselV128Expr_wrk(env
, e
);
2772 vassert(hregClass(r
) == HRcVec128
);
2773 vassert(hregIsVirtual(r
));
2777 /* DO NOT CALL THIS DIRECTLY ! */
2778 static HReg
iselV128Expr_wrk(ISelEnv
* env
, IRExpr
* e
) {
2779 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
2781 vassert(ty
== Ity_V128
);
2783 if (e
->tag
== Iex_RdTmp
) {
2784 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
2787 if (e
->tag
== Iex_Load
) {
2788 vassert (e
->Iex
.Load
.ty
== Ity_V128
);
2789 HReg v_dst
= newVRegV(env
);
2790 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, 0, iselWordExpr_R(env
,
2791 e
->Iex
.Load
.addr
), v_dst
, MSA_B
));
2795 if (e
->tag
== Iex_Get
) {
2796 HReg v_dst
= newVRegV(env
);
2797 #if defined(_MIPSEB)
2798 HReg r_addr
= newVRegI(env
);
2799 addInstr(env
, MIPSInstr_Alu(mode64
? Malu_DADD
: Malu_ADD
, r_addr
, GuestStatePointer(mode64
),
2800 MIPSRH_Imm(False
, e
->Iex
.Get
.offset
)));
2801 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, 0, r_addr
, v_dst
, MSA_B
));
2803 vassert(!(e
->Iex
.Get
.offset
& 7));
2804 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, e
->Iex
.Get
.offset
>> 3,
2805 GuestStatePointer(mode64
), v_dst
, MSA_D
));
2810 if (e
->tag
== Iex_Unop
) {
2811 IROp op_unop
= e
->Iex
.Unop
.op
;
2815 HReg v_dst
= newVRegV(env
);
2816 HReg v_help
= newVRegV(env
);
2817 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2819 MIPSInstr_Msa3R(MSA_SUBV
, MSA_D
, v_help
, v_src
, v_src
));
2821 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_D
,
2822 v_dst
, v_src
, v_help
));
2827 HReg v_dst
= newVRegV(env
);
2828 HReg v_help
= newVRegV(env
);
2829 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2831 MIPSInstr_Msa3R(MSA_SUBV
, MSA_W
, v_help
, v_src
, v_src
));
2833 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_W
,
2834 v_dst
, v_src
, v_help
));
2839 HReg v_dst
= newVRegV(env
);
2840 HReg v_help
= newVRegV(env
);
2841 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2843 MIPSInstr_Msa3R(MSA_SUBV
, MSA_H
, v_help
, v_src
, v_src
));
2845 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_H
,
2846 v_dst
, v_src
, v_help
));
2851 HReg v_dst
= newVRegV(env
);
2852 HReg v_help
= newVRegV(env
);
2853 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2855 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
, v_help
, v_src
, v_src
));
2857 MIPSInstr_Msa3R(MSA_ADD_A
, MSA_B
,
2858 v_dst
, v_src
, v_help
));
2863 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2864 HReg res
= newVRegV(env
);
2865 addInstr(env
, MIPSInstr_Msa2R(MSA_PCNT
, MSA_B
, v_src
, res
));
2870 HReg v_dst
= newVRegV(env
);
2871 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2872 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_src
, v_src
));
2876 case Iop_Reverse8sIn16_x8
: {
2877 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2878 HReg v_tmp
= newVRegV(env
);
2880 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2882 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2886 case Iop_Reverse8sIn32_x4
: {
2887 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2888 HReg v_tmp
= newVRegV(env
);
2890 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
, v_tmp
, v_src
, v_src
));
2892 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
, v_src
, v_tmp
, v_src
));
2894 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2896 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2900 case Iop_Reverse8sIn64_x2
: {
2901 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2902 HReg v_tmp
= newVRegV(env
);
2904 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_W
, v_tmp
, v_src
, v_src
));
2906 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_W
, v_src
, v_tmp
, v_src
));
2908 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
, v_tmp
, v_src
, v_src
));
2910 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
, v_src
, v_tmp
, v_src
));
2912 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
, v_tmp
, v_src
, v_src
));
2914 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
, v_src
, v_tmp
, v_src
));
2919 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2920 HReg v_dst
= newVRegV(env
);
2921 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_B
, v_src
, v_dst
));
2926 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2927 HReg v_dst
= newVRegV(env
);
2928 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_H
, v_src
, v_dst
));
2933 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2934 HReg v_dst
= newVRegV(env
);
2935 addInstr(env
, MIPSInstr_Msa2R(MSA_NLOC
, MSA_W
, v_src
, v_dst
));
2940 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2941 HReg v_dst
= newVRegV(env
);
2942 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_B
, v_src
, v_dst
));
2947 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2948 HReg v_dst
= newVRegV(env
);
2949 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_H
, v_src
, v_dst
));
2954 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2955 HReg v_dst
= newVRegV(env
);
2956 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_W
, v_src
, v_dst
));
2961 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2962 HReg v_dst
= newVRegV(env
);
2963 addInstr(env
, MIPSInstr_Msa2R(MSA_NLZC
, MSA_D
, v_src
, v_dst
));
2967 case Iop_Abs32Fx4
: {
2968 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2969 HReg v_dst
= newVRegV(env
);
2970 HReg v_help
= newVRegV(env
);
2972 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_WH
,
2973 v_help
, v_src
, v_src
));
2975 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_WH
, v_dst
, v_help
));
2979 case Iop_Abs64Fx2
: {
2980 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2981 HReg v_dst
= newVRegV(env
);
2982 HReg v_help
= newVRegV(env
);
2984 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_DW
,
2985 v_help
, v_src
, v_src
));
2987 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_DW
, v_dst
, v_help
));
2991 case Iop_RecipEst32Fx4
: {
2992 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
2993 HReg v_dst
= newVRegV(env
);
2994 set_guest_MIPS_rounding_mode_MSA(env
);
2996 MIPSInstr_Msa2RF(MSA_FRCP
, MSA_F_WH
, v_dst
, v_src
));
2997 set_MIPS_rounding_default_MSA(env
);
3001 case Iop_RecipEst64Fx2
: {
3002 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3003 HReg v_dst
= newVRegV(env
);
3004 set_guest_MIPS_rounding_mode_MSA(env
);
3006 MIPSInstr_Msa2RF(MSA_FRCP
, MSA_F_DW
, v_dst
, v_src
));
3007 set_MIPS_rounding_default_MSA(env
);
3011 case Iop_RSqrtEst32Fx4
: {
3012 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3013 HReg v_dst
= newVRegV(env
);
3014 set_guest_MIPS_rounding_mode_MSA(env
);
3016 MIPSInstr_Msa2RF(MSA_FRSQRT
, MSA_F_WH
, v_dst
, v_src
));
3017 set_MIPS_rounding_default_MSA(env
);
3021 case Iop_RSqrtEst64Fx2
: {
3022 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3023 HReg v_dst
= newVRegV(env
);
3024 set_guest_MIPS_rounding_mode_MSA(env
);
3026 MIPSInstr_Msa2RF(MSA_FRSQRT
, MSA_F_DW
, v_dst
, v_src
));
3027 set_MIPS_rounding_default_MSA(env
);
3031 case Iop_F16toF32x4
: {
3032 HReg v_dst
= newVRegV(env
);
3036 r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
3038 MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src
, v_dst
));
3040 MIPSInstr_MsaElm(MSA_INSERT
, r_src
, v_dst
,
3043 HReg r_srch
, r_srcl
;
3044 iselInt64Expr(&r_srch
, &r_srcl
, env
, e
->Iex
.Unop
.arg
);
3046 MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_srcl
, v_dst
));
3048 MIPSInstr_MsaElm(MSA_INSERT
, r_srch
, v_dst
,
3051 MIPSInstr_MsaElm(MSA_INSERT
, r_srcl
, v_dst
,
3054 MIPSInstr_MsaElm(MSA_INSERT
, r_srch
, v_dst
,
3059 MIPSInstr_Msa2RF(MSA_FEXUPR
, MSA_F_WH
, v_dst
, v_dst
));
3063 case Iop_I32UtoF32x4_DEP
: {
3064 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3065 HReg v_dst
= newVRegV(env
);
3066 set_guest_MIPS_rounding_mode_MSA(env
);
3068 MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_WH
, v_dst
, v_src
));
3069 set_MIPS_rounding_default_MSA(env
);
3073 case Iop_F32toI32Sx4_RZ
: {
3074 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3075 HReg v_dst
= newVRegV(env
);
3077 MIPSInstr_Msa2RF(MSA_FTRUNC_S
, MSA_F_WH
, v_dst
, v_src
));
3081 case Iop_F32toI32Ux4_RZ
: {
3082 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3083 HReg v_dst
= newVRegV(env
);
3085 MIPSInstr_Msa2RF(MSA_FTRUNC_U
, MSA_F_WH
, v_dst
, v_src
));
3089 case Iop_Log2_32Fx4
: {
3090 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3091 HReg v_dst
= newVRegV(env
);
3093 MIPSInstr_Msa2RF(MSA_FLOG2
, MSA_F_WH
, v_dst
, v_src
));
3097 case Iop_Log2_64Fx2
: {
3098 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3099 HReg v_dst
= newVRegV(env
);
3101 MIPSInstr_Msa2RF(MSA_FLOG2
, MSA_F_DW
, v_dst
, v_src
));
3104 case Iop_CmpNEZ8x16
: {
3105 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3106 HReg v_dst
= newVRegV(env
);
3107 HReg zero
= Zero(mode64
);
3108 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3110 MIPSInstr_Msa3R(MSA_CEQ
, MSA_B
, v_dst
, v_src
, v_dst
));
3111 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3114 case Iop_CmpNEZ16x8
: {
3115 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3116 HReg v_dst
= newVRegV(env
);
3117 HReg zero
= Zero(mode64
);
3118 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3120 MIPSInstr_Msa3R(MSA_CEQ
, MSA_H
, v_dst
, v_src
, v_dst
));
3121 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3124 case Iop_CmpNEZ32x4
: {
3125 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3126 HReg v_dst
= newVRegV(env
);
3127 HReg zero
= Zero(mode64
);
3128 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3130 MIPSInstr_Msa3R(MSA_CEQ
, MSA_W
, v_dst
, v_src
, v_dst
));
3131 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3134 case Iop_CmpNEZ64x2
: {
3135 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
3136 HReg v_dst
= newVRegV(env
);
3137 HReg zero
= Zero(mode64
);
3138 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
3140 MIPSInstr_Msa3R(MSA_CEQ
, MSA_D
, v_dst
, v_src
, v_dst
));
3141 addInstr(env
, MIPSInstr_MsaVec(MSA_NORV
, v_dst
, v_dst
, v_dst
));
3145 vex_printf("iselV128Expr_wrk: Unsupported unop: %u\n", op_unop
);
3149 if (e
->tag
== Iex_Binop
) {
3150 IROp op_binop
= e
->Iex
.Binop
.op
;
3154 HReg v_dst
= newVRegV(env
);
3155 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3156 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3158 MIPSInstr_Msa3R(MSA_ADDV
, MSA_B
,
3159 v_dst
, v_src1
, v_src2
));
3164 HReg v_dst
= newVRegV(env
);
3165 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3166 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3168 MIPSInstr_Msa3R(MSA_ADDV
, MSA_H
,
3169 v_dst
, v_src1
, v_src2
));
3174 HReg v_dst
= newVRegV(env
);
3175 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3176 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3178 MIPSInstr_Msa3R(MSA_ADDV
, MSA_W
,
3179 v_dst
, v_src1
, v_src2
));
3184 HReg v_dst
= newVRegV(env
);
3185 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3186 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3188 MIPSInstr_Msa3R(MSA_ADDV
, MSA_D
,
3189 v_dst
, v_src1
, v_src2
));
3194 HReg v_dst
= newVRegV(env
);
3195 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3196 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3198 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
3199 v_dst
, v_src1
, v_src2
));
3204 HReg v_dst
= newVRegV(env
);
3205 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3206 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3208 MIPSInstr_Msa3R(MSA_SUBV
, MSA_H
,
3209 v_dst
, v_src1
, v_src2
));
3214 HReg v_dst
= newVRegV(env
);
3215 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3216 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3218 MIPSInstr_Msa3R(MSA_SUBV
, MSA_W
,
3219 v_dst
, v_src1
, v_src2
));
3224 HReg v_dst
= newVRegV(env
);
3225 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3226 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3228 MIPSInstr_Msa3R(MSA_SUBV
, MSA_D
,
3229 v_dst
, v_src1
, v_src2
));
3233 case Iop_QAdd8Sx16
: {
3234 HReg v_dst
= newVRegV(env
);
3235 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3236 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3238 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_B
,
3239 v_dst
, v_src1
, v_src2
));
3243 case Iop_QAdd16Sx8
: {
3244 HReg v_dst
= newVRegV(env
);
3245 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3246 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3248 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_H
,
3249 v_dst
, v_src1
, v_src2
));
3253 case Iop_QAdd32Sx4
: {
3254 HReg v_dst
= newVRegV(env
);
3255 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3256 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3258 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_W
,
3259 v_dst
, v_src1
, v_src2
));
3263 case Iop_QAdd64Sx2
: {
3264 HReg v_dst
= newVRegV(env
);
3265 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3266 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3268 MIPSInstr_Msa3R(MSA_ADDS_S
, MSA_D
,
3269 v_dst
, v_src1
, v_src2
));
3273 case Iop_QAdd8Ux16
: {
3274 HReg v_dst
= newVRegV(env
);
3275 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3276 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3278 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_B
,
3279 v_dst
, v_src1
, v_src2
));
3283 case Iop_QAdd16Ux8
: {
3284 HReg v_dst
= newVRegV(env
);
3285 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3286 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3288 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_H
,
3289 v_dst
, v_src1
, v_src2
));
3293 case Iop_QAdd32Ux4
: {
3294 HReg v_dst
= newVRegV(env
);
3295 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3296 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3298 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_W
,
3299 v_dst
, v_src1
, v_src2
));
3303 case Iop_QAdd64Ux2
: {
3304 HReg v_dst
= newVRegV(env
);
3305 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3306 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3308 MIPSInstr_Msa3R(MSA_ADDS_U
, MSA_D
,
3309 v_dst
, v_src1
, v_src2
));
3313 case Iop_QSub8Sx16
: {
3314 HReg v_dst
= newVRegV(env
);
3315 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3316 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3318 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_B
,
3319 v_dst
, v_src1
, v_src2
));
3323 case Iop_QSub16Sx8
: {
3324 HReg v_dst
= newVRegV(env
);
3325 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3326 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3328 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_H
,
3329 v_dst
, v_src1
, v_src2
));
3333 case Iop_QSub32Sx4
: {
3334 HReg v_dst
= newVRegV(env
);
3335 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3336 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3338 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_W
,
3339 v_dst
, v_src1
, v_src2
));
3343 case Iop_QSub64Sx2
: {
3344 HReg v_dst
= newVRegV(env
);
3345 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3346 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3348 MIPSInstr_Msa3R(MSA_SUBS_S
, MSA_D
,
3349 v_dst
, v_src1
, v_src2
));
3353 case Iop_QSub8Ux16
: {
3354 HReg v_dst
= newVRegV(env
);
3355 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3356 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3358 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_B
,
3359 v_dst
, v_src1
, v_src2
));
3363 case Iop_QSub16Ux8
: {
3364 HReg v_dst
= newVRegV(env
);
3365 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3366 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3368 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_H
,
3369 v_dst
, v_src1
, v_src2
));
3373 case Iop_QSub32Ux4
: {
3374 HReg v_dst
= newVRegV(env
);
3375 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3376 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3378 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_W
,
3379 v_dst
, v_src1
, v_src2
));
3383 case Iop_QSub64Ux2
: {
3384 HReg v_dst
= newVRegV(env
);
3385 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3386 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3388 MIPSInstr_Msa3R(MSA_SUBS_U
, MSA_D
,
3389 v_dst
, v_src1
, v_src2
));
3393 case Iop_QDMulHi32Sx4
: {
3394 HReg v_dst
= newVRegV(env
);
3395 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3396 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3398 MIPSInstr_Msa3RF(MSA_MUL_Q
, MSA_F_DW
,
3399 v_dst
, v_src1
, v_src2
));
3403 case Iop_QDMulHi16Sx8
: {
3404 HReg v_dst
= newVRegV(env
);
3405 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3406 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3408 MIPSInstr_Msa3RF(MSA_MUL_Q
, MSA_F_WH
,
3409 v_dst
, v_src1
, v_src2
));
3413 case Iop_QRDMulHi32Sx4
: {
3414 HReg v_dst
= newVRegV(env
);
3415 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3416 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3418 MIPSInstr_Msa3RF(MSA_MULR_Q
, MSA_F_DW
,
3419 v_dst
, v_src1
, v_src2
));
3423 case Iop_QRDMulHi16Sx8
: {
3424 HReg v_dst
= newVRegV(env
);
3425 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3426 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3428 MIPSInstr_Msa3RF(MSA_MULR_Q
, MSA_F_WH
,
3429 v_dst
, v_src1
, v_src2
));
3433 case Iop_Max8Sx16
: {
3434 HReg v_dst
= newVRegV(env
);
3435 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3436 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3438 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_B
,
3439 v_dst
, v_src1
, v_src2
));
3443 case Iop_Max16Sx8
: {
3444 HReg v_dst
= newVRegV(env
);
3445 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3446 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3448 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_H
,
3449 v_dst
, v_src1
, v_src2
));
3453 case Iop_Max32Sx4
: {
3454 HReg v_dst
= newVRegV(env
);
3455 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3456 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3458 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_W
,
3459 v_dst
, v_src1
, v_src2
));
3463 case Iop_Max64Sx2
: {
3464 HReg v_dst
= newVRegV(env
);
3465 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3466 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3468 MIPSInstr_Msa3R(MSA_MAX_S
, MSA_D
,
3469 v_dst
, v_src1
, v_src2
));
3473 case Iop_Max8Ux16
: {
3474 HReg v_dst
= newVRegV(env
);
3475 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3476 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3478 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_B
,
3479 v_dst
, v_src1
, v_src2
));
3483 case Iop_Max16Ux8
: {
3484 HReg v_dst
= newVRegV(env
);
3485 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3486 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3488 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_H
,
3489 v_dst
, v_src1
, v_src2
));
3493 case Iop_Max32Ux4
: {
3494 HReg v_dst
= newVRegV(env
);
3495 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3496 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3498 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_W
,
3499 v_dst
, v_src1
, v_src2
));
3503 case Iop_Max64Ux2
: {
3504 HReg v_dst
= newVRegV(env
);
3505 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3506 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3508 MIPSInstr_Msa3R(MSA_MAX_U
, MSA_D
,
3509 v_dst
, v_src1
, v_src2
));
3513 case Iop_Min8Sx16
: {
3514 HReg v_dst
= newVRegV(env
);
3515 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3516 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3518 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_B
,
3519 v_dst
, v_src1
, v_src2
));
3523 case Iop_Min16Sx8
: {
3524 HReg v_dst
= newVRegV(env
);
3525 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3526 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3528 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_H
,
3529 v_dst
, v_src1
, v_src2
));
3533 case Iop_Min32Sx4
: {
3534 HReg v_dst
= newVRegV(env
);
3535 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3536 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3538 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_W
,
3539 v_dst
, v_src1
, v_src2
));
3543 case Iop_Min64Sx2
: {
3544 HReg v_dst
= newVRegV(env
);
3545 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3546 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3548 MIPSInstr_Msa3R(MSA_MIN_S
, MSA_D
,
3549 v_dst
, v_src1
, v_src2
));
3553 case Iop_Min8Ux16
: {
3554 HReg v_dst
= newVRegV(env
);
3555 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3556 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3558 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_B
,
3559 v_dst
, v_src1
, v_src2
));
3563 case Iop_Min16Ux8
: {
3564 HReg v_dst
= newVRegV(env
);
3565 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3566 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3568 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_H
,
3569 v_dst
, v_src1
, v_src2
));
3573 case Iop_Min32Ux4
: {
3574 HReg v_dst
= newVRegV(env
);
3575 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3576 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3578 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_W
,
3579 v_dst
, v_src1
, v_src2
));
3583 case Iop_Min64Ux2
: {
3584 HReg v_dst
= newVRegV(env
);
3585 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3586 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3588 MIPSInstr_Msa3R(MSA_MIN_U
, MSA_D
,
3589 v_dst
, v_src1
, v_src2
));
3594 HReg v_dst
= newVRegV(env
);
3595 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3596 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3598 MIPSInstr_Msa3R(MSA_SLL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3603 HReg v_dst
= newVRegV(env
);
3604 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3605 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3607 MIPSInstr_Msa3R(MSA_SLL
, MSA_H
, v_dst
, v_src1
, v_src2
));
3612 HReg v_dst
= newVRegV(env
);
3613 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3614 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3616 MIPSInstr_Msa3R(MSA_SLL
, MSA_W
, v_dst
, v_src1
, v_src2
));
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_SLL
, MSA_D
, v_dst
, v_src1
, v_src2
));
3630 HReg v_dst
= newVRegV(env
);
3631 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3632 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3634 MIPSInstr_Msa3R(MSA_SRL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3639 HReg v_dst
= newVRegV(env
);
3640 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3641 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3643 MIPSInstr_Msa3R(MSA_SRL
, MSA_H
, v_dst
, v_src1
, v_src2
));
3648 HReg v_dst
= newVRegV(env
);
3649 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3650 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3652 MIPSInstr_Msa3R(MSA_SRL
, MSA_W
, v_dst
, v_src1
, v_src2
));
3657 HReg v_dst
= newVRegV(env
);
3658 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3659 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3661 MIPSInstr_Msa3R(MSA_SRL
, MSA_D
, v_dst
, v_src1
, v_src2
));
3666 HReg v_dst
= newVRegV(env
);
3667 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3668 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3670 MIPSInstr_Msa3R(MSA_SRA
, MSA_B
, v_dst
, v_src1
, v_src2
));
3675 HReg v_dst
= newVRegV(env
);
3676 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3677 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3679 MIPSInstr_Msa3R(MSA_SRA
, MSA_H
, v_dst
, v_src1
, v_src2
));
3684 HReg v_dst
= newVRegV(env
);
3685 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3686 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3688 MIPSInstr_Msa3R(MSA_SRA
, MSA_W
, v_dst
, v_src1
, v_src2
));
3693 HReg v_dst
= newVRegV(env
);
3694 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3695 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3697 MIPSInstr_Msa3R(MSA_SRA
, MSA_D
, v_dst
, v_src1
, v_src2
));
3701 case Iop_InterleaveHI8x16
: {
3702 HReg v_dst
= newVRegV(env
);
3703 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3704 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3706 MIPSInstr_Msa3R(MSA_ILVL
, MSA_B
, v_dst
, v_src1
, v_src2
));
3710 case Iop_InterleaveHI16x8
: {
3711 HReg v_dst
= newVRegV(env
);
3712 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3713 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3715 MIPSInstr_Msa3R(MSA_ILVL
, MSA_H
,
3716 v_dst
, v_src1
, v_src2
));
3720 case Iop_InterleaveHI32x4
: {
3721 HReg v_dst
= newVRegV(env
);
3722 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3723 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3725 MIPSInstr_Msa3R(MSA_ILVL
, MSA_W
,
3726 v_dst
, v_src1
, v_src2
));
3730 case Iop_InterleaveHI64x2
: {
3731 HReg v_dst
= newVRegV(env
);
3732 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3733 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3735 MIPSInstr_Msa3R(MSA_ILVL
, MSA_D
,
3736 v_dst
, v_src1
, v_src2
));
3740 case Iop_InterleaveLO8x16
: {
3741 HReg v_dst
= newVRegV(env
);
3742 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3743 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3745 MIPSInstr_Msa3R(MSA_ILVR
, MSA_B
,
3746 v_dst
, v_src1
, v_src2
));
3750 case Iop_InterleaveLO16x8
: {
3751 HReg v_dst
= newVRegV(env
);
3752 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3753 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3755 MIPSInstr_Msa3R(MSA_ILVR
, MSA_H
,
3756 v_dst
, v_src1
, v_src2
));
3760 case Iop_InterleaveLO32x4
: {
3761 HReg v_dst
= newVRegV(env
);
3762 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3763 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3765 MIPSInstr_Msa3R(MSA_ILVR
, MSA_W
,
3766 v_dst
, v_src1
, v_src2
));
3770 case Iop_InterleaveLO64x2
: {
3771 HReg v_dst
= newVRegV(env
);
3772 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3773 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3775 MIPSInstr_Msa3R(MSA_ILVR
, MSA_D
,
3776 v_dst
, v_src1
, v_src2
));
3780 case Iop_InterleaveEvenLanes8x16
: {
3781 HReg v_dst
= newVRegV(env
);
3782 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3783 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3785 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_B
,
3786 v_dst
, v_src1
, v_src2
));
3790 case Iop_InterleaveEvenLanes16x8
: {
3791 HReg v_dst
= newVRegV(env
);
3792 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3793 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3795 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_H
,
3796 v_dst
, v_src1
, v_src2
));
3800 case Iop_InterleaveEvenLanes32x4
: {
3801 HReg v_dst
= newVRegV(env
);
3802 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3803 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3805 MIPSInstr_Msa3R(MSA_ILVEV
, MSA_W
,
3806 v_dst
, v_src1
, v_src2
));
3810 case Iop_InterleaveOddLanes8x16
: {
3811 HReg v_dst
= newVRegV(env
);
3812 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3813 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3815 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_B
,
3816 v_dst
, v_src1
, v_src2
));
3820 case Iop_InterleaveOddLanes16x8
: {
3821 HReg v_dst
= newVRegV(env
);
3822 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3823 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3825 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_H
,
3826 v_dst
, v_src1
, v_src2
));
3830 case Iop_InterleaveOddLanes32x4
: {
3831 HReg v_dst
= newVRegV(env
);
3832 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3833 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3835 MIPSInstr_Msa3R(MSA_ILVOD
, MSA_W
,
3836 v_dst
, v_src1
, v_src2
));
3840 case Iop_PackEvenLanes8x16
: {
3841 HReg v_dst
= newVRegV(env
);
3842 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3843 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3845 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_B
,
3846 v_dst
, v_src1
, v_src2
));
3850 case Iop_PackEvenLanes16x8
: {
3851 HReg v_dst
= newVRegV(env
);
3852 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3853 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3855 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_H
,
3856 v_dst
, v_src1
, v_src2
));
3860 case Iop_PackEvenLanes32x4
: {
3861 HReg v_dst
= newVRegV(env
);
3862 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3863 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3865 MIPSInstr_Msa3R(MSA_PCKEV
, MSA_W
,
3866 v_dst
, v_src1
, v_src2
));
3870 case Iop_PackOddLanes8x16
: {
3871 HReg v_dst
= newVRegV(env
);
3872 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3873 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3875 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_B
,
3876 v_dst
, v_src1
, v_src2
));
3880 case Iop_PackOddLanes16x8
: {
3881 HReg v_dst
= newVRegV(env
);
3882 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3883 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3885 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_H
,
3886 v_dst
, v_src1
, v_src2
));
3890 case Iop_PackOddLanes32x4
: {
3891 HReg v_dst
= newVRegV(env
);
3892 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3893 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3895 MIPSInstr_Msa3R(MSA_PCKOD
, MSA_W
,
3896 v_dst
, v_src1
, v_src2
));
3900 case Iop_CmpEQ8x16
: {
3901 HReg v_dst
= newVRegV(env
);
3902 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3903 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3905 MIPSInstr_Msa3R(MSA_CEQ
, MSA_B
, v_dst
, v_src1
, v_src2
));
3909 case Iop_CmpEQ16x8
: {
3910 HReg v_dst
= newVRegV(env
);
3911 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3912 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3914 MIPSInstr_Msa3R(MSA_CEQ
, MSA_H
, v_dst
, v_src1
, v_src2
));
3918 case Iop_CmpEQ32x4
: {
3919 HReg v_dst
= newVRegV(env
);
3920 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3921 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3923 MIPSInstr_Msa3R(MSA_CEQ
, MSA_W
, v_dst
, v_src1
, v_src2
));
3927 case Iop_CmpEQ64x2
: {
3928 HReg v_dst
= newVRegV(env
);
3929 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3930 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3932 MIPSInstr_Msa3R(MSA_CEQ
, MSA_D
, v_dst
, v_src1
, v_src2
));
3936 case Iop_CmpGT8Sx16
: {
3937 HReg v_dst
= newVRegV(env
);
3938 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3939 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3941 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_B
,
3942 v_dst
, v_src2
, v_src1
));
3946 case Iop_CmpGT16Sx8
: {
3947 HReg v_dst
= newVRegV(env
);
3948 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3949 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3951 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_H
,
3952 v_dst
, v_src2
, v_src1
));
3956 case Iop_CmpGT32Sx4
: {
3957 HReg v_dst
= newVRegV(env
);
3958 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3959 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3961 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_W
,
3962 v_dst
, v_src2
, v_src1
));
3966 case Iop_CmpGT64Sx2
: {
3967 HReg v_dst
= newVRegV(env
);
3968 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3969 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3971 MIPSInstr_Msa3R(MSA_CLT_S
, MSA_D
,
3972 v_dst
, v_src2
, v_src1
));
3976 case Iop_CmpGT8Ux16
: {
3977 HReg v_dst
= newVRegV(env
);
3978 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3979 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3981 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_B
,
3982 v_dst
, v_src2
, v_src1
));
3986 case Iop_CmpGT16Ux8
: {
3987 HReg v_dst
= newVRegV(env
);
3988 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3989 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
3991 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_H
,
3992 v_dst
, v_src2
, v_src1
));
3996 case Iop_CmpGT32Ux4
: {
3997 HReg v_dst
= newVRegV(env
);
3998 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
3999 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4001 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_W
,
4002 v_dst
, v_src2
, v_src1
));
4006 case Iop_CmpGT64Ux2
: {
4007 HReg v_dst
= newVRegV(env
);
4008 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4009 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4011 MIPSInstr_Msa3R(MSA_CLT_U
, MSA_D
,
4012 v_dst
, v_src2
, v_src1
));
4016 case Iop_Avg8Sx16
: {
4017 HReg v_dst
= newVRegV(env
);
4018 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4019 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4021 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_B
,
4022 v_dst
, v_src1
, v_src2
));
4026 case Iop_Avg16Sx8
: {
4027 HReg v_dst
= newVRegV(env
);
4028 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4029 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4031 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_H
,
4032 v_dst
, v_src1
, v_src2
));
4036 case Iop_Avg32Sx4
: {
4037 HReg v_dst
= newVRegV(env
);
4038 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4039 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4041 MIPSInstr_Msa3R(MSA_AVER_S
, MSA_W
,
4042 v_dst
, v_src1
, v_src2
));
4046 case Iop_Avg8Ux16
: {
4047 HReg v_dst
= newVRegV(env
);
4048 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4049 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4051 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_B
,
4052 v_dst
, v_src1
, v_src2
));
4056 case Iop_Avg16Ux8
: {
4057 HReg v_dst
= newVRegV(env
);
4058 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4059 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4061 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_H
,
4062 v_dst
, v_src1
, v_src2
));
4066 case Iop_Avg32Ux4
: {
4067 HReg v_dst
= newVRegV(env
);
4068 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4069 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4071 MIPSInstr_Msa3R(MSA_AVER_U
, MSA_W
,
4072 v_dst
, v_src1
, v_src2
));
4077 HReg v_dst
= newVRegV(env
);
4078 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4079 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4081 MIPSInstr_Msa3R(MSA_MULV
, MSA_B
,
4082 v_dst
, v_src1
, v_src2
));
4087 HReg v_dst
= newVRegV(env
);
4088 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4089 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4091 MIPSInstr_Msa3R(MSA_MULV
, MSA_H
,
4092 v_dst
, v_src1
, v_src2
));
4097 HReg v_dst
= newVRegV(env
);
4098 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4099 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4101 MIPSInstr_Msa3R(MSA_MULV
, MSA_W
,
4102 v_dst
, v_src1
, v_src2
));
4107 HReg v_dst
= newVRegV(env
);
4108 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4109 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4110 addInstr(env
, MIPSInstr_MsaVec(MSA_ANDV
, v_dst
, v_src1
, v_src2
));
4115 HReg v_dst
= newVRegV(env
);
4116 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4117 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4118 addInstr(env
, MIPSInstr_MsaVec(MSA_ORV
, v_dst
, v_src1
, v_src2
));
4123 HReg v_dst
= newVRegV(env
);
4124 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4125 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4126 addInstr(env
, MIPSInstr_MsaVec(MSA_XORV
, v_dst
, v_src1
, v_src2
));
4131 HReg v_dst
= newVRegV(env
);
4132 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4134 sm
= iselWordExpr_RH7u(env
, e
->Iex
.Binop
.arg2
);
4136 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
4137 v_dst
, v_src1
, v_src1
));
4139 if (sm
->tag
== Mrh_Imm
) {
4140 int n
= (sm
->Mrh
.Imm
.imm16
) >> 3;
4142 MIPSInstr_MsaElm(MSA_SLDI
, v_src1
, v_dst
,
4145 HReg v_src2
= sm
->Mrh
.Reg
.reg
;
4146 MIPSRH
*ri
= MIPSRH_Imm(False
, 3);
4147 HReg r_dst
= newVRegI(env
);
4148 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/*32bit shift */,
4149 r_dst
, v_src2
, ri
));
4151 MIPSInstr_Msa3R(MSA_SLD
, MSA_B
,
4152 v_dst
, v_src1
, r_dst
));
4159 HReg v_dst
= newVRegV(env
);
4160 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4162 sm
= iselWordExpr_RH7u(env
, e
->Iex
.Binop
.arg2
);
4164 MIPSInstr_Msa3R(MSA_SUBV
, MSA_B
,
4165 v_dst
, v_src1
, v_src1
));
4167 if (sm
->tag
== Mrh_Imm
) {
4168 int n
= 16 - ((sm
->Mrh
.Imm
.imm16
) >> 3);
4173 MIPSInstr_MsaElm(MSA_SLDI
, v_dst
, v_src1
,
4176 HReg v_src2
= sm
->Mrh
.Reg
.reg
;
4177 MIPSRH
*ri
= MIPSRH_Imm(False
, 3);
4178 HReg r_dst
= newVRegI(env
);
4179 HReg help
= newVRegI(env
);
4180 addInstr(env
, MIPSInstr_Alu(Malu_XOR
, help
, v_src2
, sm
));
4181 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, help
, help
, sm
));
4182 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/*32bit shift */,
4185 MIPSInstr_Msa3R(MSA_SLD
, MSA_B
,
4186 v_src1
, v_dst
, r_dst
));
4192 case Iop_ShlN8x16
: {
4193 HReg v_dst
= newVRegV(env
);
4194 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4195 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4196 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4197 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4199 MIPSInstr_MsaBit(MSA_SLLI
, MSA_B
,
4200 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4205 case Iop_ShlN16x8
: {
4206 HReg v_dst
= newVRegV(env
);
4207 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4208 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4209 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4210 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4212 MIPSInstr_MsaBit(MSA_SLLI
, MSA_H
,
4213 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4218 case Iop_ShlN32x4
: {
4219 HReg v_dst
= newVRegV(env
);
4220 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4221 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4222 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4223 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4225 MIPSInstr_MsaBit(MSA_SLLI
, MSA_W
,
4226 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4231 case Iop_ShlN64x2
: {
4232 HReg v_dst
= newVRegV(env
);
4233 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4234 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4235 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4236 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4238 MIPSInstr_MsaBit(MSA_SLLI
, MSA_D
,
4239 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4244 case Iop_SarN8x16
: {
4245 HReg v_dst
= newVRegV(env
);
4246 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4247 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4248 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4249 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4251 MIPSInstr_MsaBit(MSA_SRAI
, MSA_B
,
4252 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4257 case Iop_SarN16x8
: {
4258 HReg v_dst
= newVRegV(env
);
4259 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4260 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4261 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4262 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4264 MIPSInstr_MsaBit(MSA_SRAI
, MSA_H
,
4265 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4270 case Iop_SarN32x4
: {
4271 HReg v_dst
= newVRegV(env
);
4272 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4273 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4274 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4275 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4277 MIPSInstr_MsaBit(MSA_SRAI
, MSA_W
,
4278 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4283 case Iop_SarN64x2
: {
4284 HReg v_dst
= newVRegV(env
);
4285 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4286 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4287 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4288 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4290 MIPSInstr_MsaBit(MSA_SRAI
, MSA_D
,
4291 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4296 case Iop_ShrN8x16
: {
4297 HReg v_dst
= newVRegV(env
);
4298 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4299 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4300 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4301 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4303 MIPSInstr_MsaBit(MSA_SRLI
, MSA_B
,
4304 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4309 case Iop_ShrN16x8
: {
4310 HReg v_dst
= newVRegV(env
);
4311 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4312 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4313 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4314 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4316 MIPSInstr_MsaBit(MSA_SRLI
, MSA_H
,
4317 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4322 case Iop_ShrN32x4
: {
4323 HReg v_dst
= newVRegV(env
);
4324 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4325 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4326 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4327 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4329 MIPSInstr_MsaBit(MSA_SRLI
, MSA_W
,
4330 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4335 case Iop_ShrN64x2
: {
4336 HReg v_dst
= newVRegV(env
);
4337 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4338 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4339 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4340 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4342 MIPSInstr_MsaBit(MSA_SRLI
, MSA_D
,
4343 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4348 case Iop_QandQSarNnarrow64Sto32Sx2
: {
4349 HReg v_dst
= newVRegV(env
);
4350 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4351 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4352 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4353 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4355 MIPSInstr_MsaBit(MSA_SRAI
, MSA_D
,
4356 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4358 addInstr(env
, MIPSInstr_MsaBit(MSA_SAT_S
, MSA_D
, 31, v_dst
, v_dst
));
4362 case Iop_QandQSarNnarrow32Sto16Sx4
: {
4363 HReg v_dst
= newVRegV(env
);
4364 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4365 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4366 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4367 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4369 MIPSInstr_MsaBit(MSA_SRAI
, MSA_W
,
4370 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4373 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_W
, 15, v_dst
, v_dst
));
4377 case Iop_QandQRSarNnarrow64Sto32Sx2
: {
4378 HReg v_dst
= newVRegV(env
);
4379 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4380 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4381 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4382 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4384 MIPSInstr_MsaBit(MSA_SRARI
, MSA_D
,
4385 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4388 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_D
, 31, v_dst
, v_dst
));
4392 case Iop_QandQRSarNnarrow32Sto16Sx4
: {
4393 HReg v_dst
= newVRegV(env
);
4394 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4395 vassert(e
->Iex
.Binop
.arg2
->tag
== Iex_Const
);
4396 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->tag
== Ico_U8
);
4397 vassert(e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
<= 63);
4399 MIPSInstr_MsaBit(MSA_SRARI
, MSA_W
,
4400 e
->Iex
.Binop
.arg2
->Iex
.Const
.con
->Ico
.U8
,
4403 MIPSInstr_MsaBit(MSA_SAT_S
, MSA_W
, 15, v_dst
, v_dst
));
4407 case Iop_CmpEQ32Fx4
: {
4408 HReg v_dst
= newVRegV(env
);
4409 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4410 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4412 MIPSInstr_Msa3RF(MSA_FCEQ
, MSA_F_WH
,
4413 v_dst
, v_src1
, v_src2
));
4417 case Iop_CmpEQ64Fx2
: {
4418 HReg v_dst
= newVRegV(env
);
4419 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4420 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4422 MIPSInstr_Msa3RF(MSA_FCEQ
, MSA_F_DW
,
4423 v_dst
, v_src1
, v_src2
));
4427 case Iop_CmpLT32Fx4
: {
4428 HReg v_dst
= newVRegV(env
);
4429 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4430 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4432 MIPSInstr_Msa3RF(MSA_FCLT
, MSA_F_WH
,
4433 v_dst
, v_src1
, v_src2
));
4437 case Iop_CmpLT64Fx2
: {
4438 HReg v_dst
= newVRegV(env
);
4439 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4440 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4442 MIPSInstr_Msa3RF(MSA_FCLT
, MSA_F_DW
,
4443 v_dst
, v_src1
, v_src2
));
4447 case Iop_CmpLE32Fx4
: {
4448 HReg v_dst
= newVRegV(env
);
4449 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4450 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4452 MIPSInstr_Msa3RF(MSA_FCLE
, MSA_F_WH
,
4453 v_dst
, v_src1
, v_src2
));
4457 case Iop_CmpLE64Fx2
: {
4458 HReg v_dst
= newVRegV(env
);
4459 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4460 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4462 MIPSInstr_Msa3RF(MSA_FCLE
, MSA_F_DW
,
4463 v_dst
, v_src1
, v_src2
));
4467 case Iop_CmpUN32Fx4
: {
4468 HReg v_dst
= newVRegV(env
);
4469 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4470 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4472 MIPSInstr_Msa3RF(MSA_FCUN
, MSA_F_WH
,
4473 v_dst
, v_src1
, v_src2
));
4477 case Iop_CmpUN64Fx2
: {
4478 HReg v_dst
= newVRegV(env
);
4479 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4480 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4482 MIPSInstr_Msa3RF(MSA_FCUN
, MSA_F_DW
,
4483 v_dst
, v_src1
, v_src2
));
4487 case Iop_64HLtoV128
: {
4488 HReg v_dst
= newVRegV(env
);
4493 r_src1
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4494 r_src2
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4496 MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src2
, v_dst
));
4498 MIPSInstr_MsaElm(MSA_INSERT
, r_src1
, v_dst
,
4501 HReg r_src1h
, r_src1l
;
4502 HReg r_src2h
, r_src2l
;
4503 iselInt64Expr(&r_src1h
, &r_src1l
, env
, e
->Iex
.Binop
.arg1
);
4504 iselInt64Expr(&r_src2h
, &r_src2l
, env
, e
->Iex
.Binop
.arg2
);
4506 MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_src2l
, v_dst
));
4508 MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, v_dst
,
4511 MIPSInstr_MsaElm(MSA_INSERT
, r_src1l
, v_dst
,
4514 MIPSInstr_MsaElm(MSA_INSERT
, r_src1h
, v_dst
,
4521 case Iop_Min32Fx4
: {
4522 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4523 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4524 HReg v_dst
= newVRegV(env
);
4526 MIPSInstr_Msa3RF(MSA_FMIN
, MSA_F_WH
,
4527 v_dst
, v_src1
, v_src2
));
4531 case Iop_Min64Fx2
: {
4532 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4533 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4534 HReg v_dst
= newVRegV(env
);
4536 MIPSInstr_Msa3RF(MSA_FMIN
, MSA_F_DW
,
4537 v_dst
, v_src1
, v_src2
));
4541 case Iop_Max32Fx4
: {
4542 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4543 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4544 HReg v_dst
= newVRegV(env
);
4546 MIPSInstr_Msa3RF(MSA_FMAX
, MSA_F_WH
,
4547 v_dst
, v_src1
, v_src2
));
4551 case Iop_Max64Fx2
: {
4552 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
4553 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4554 HReg v_dst
= newVRegV(env
);
4556 MIPSInstr_Msa3RF(MSA_FMAX
, MSA_F_DW
,
4557 v_dst
, v_src1
, v_src2
));
4561 case Iop_Sqrt32Fx4
: {
4562 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4563 HReg v_dst
= newVRegV(env
);
4564 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
4566 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_WH
, v_dst
, v_src
));
4567 set_MIPS_rounding_default_MSA(env
);
4571 case Iop_Sqrt64Fx2
: {
4572 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg2
);
4573 HReg v_dst
= newVRegV(env
);
4574 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
4576 MIPSInstr_Msa2RF(MSA_FSQRT
, MSA_F_DW
, v_dst
, v_src
));
4577 set_MIPS_rounding_default_MSA(env
);
4582 vex_printf("iselV128Expr_wrk: unsupported binop: %x\n", op_binop
);
4586 if (e
->tag
== Iex_Triop
) {
4587 IROp op_triop
= e
->Iex
.Triop
.details
->op
;
4590 case Iop_Add32Fx4
: {
4591 HReg v_dst
= newVRegV(env
);
4592 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4593 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4594 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4596 MIPSInstr_Msa3RF(MSA_FADD
, MSA_F_WH
,
4597 v_dst
, v_src1
, v_src2
));
4598 set_MIPS_rounding_default_MSA(env
);
4602 case Iop_Add64Fx2
: {
4603 HReg v_dst
= newVRegV(env
);
4604 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4605 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4606 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4608 MIPSInstr_Msa3RF(MSA_FADD
, MSA_F_DW
,
4609 v_dst
, v_src1
, v_src2
));
4610 set_MIPS_rounding_default_MSA(env
);
4614 case Iop_Sub32Fx4
: {
4615 HReg v_dst
= newVRegV(env
);
4616 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4617 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4618 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4620 MIPSInstr_Msa3RF(MSA_FSUB
, MSA_F_WH
,
4621 v_dst
, v_src1
, v_src2
));
4622 set_MIPS_rounding_default_MSA(env
);
4626 case Iop_Sub64Fx2
: {
4627 HReg v_dst
= newVRegV(env
);
4628 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4629 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4630 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4632 MIPSInstr_Msa3RF(MSA_FSUB
, MSA_F_DW
,
4633 v_dst
, v_src1
, v_src2
));
4634 set_MIPS_rounding_default_MSA(env
);
4638 case Iop_Mul32Fx4
: {
4639 HReg v_dst
= newVRegV(env
);
4640 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4641 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4642 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4644 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_WH
,
4645 v_dst
, v_src1
, v_src2
));
4646 set_MIPS_rounding_default_MSA(env
);
4650 case Iop_Mul64Fx2
: {
4651 HReg v_dst
= newVRegV(env
);
4652 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4653 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4654 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4656 MIPSInstr_Msa3RF(MSA_FMUL
, MSA_F_DW
,
4657 v_dst
, v_src1
, v_src2
));
4658 set_MIPS_rounding_default_MSA(env
);
4662 case Iop_Div32Fx4
: {
4663 HReg v_dst
= newVRegV(env
);
4664 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4665 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4666 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4668 MIPSInstr_Msa3RF(MSA_FDIV
, MSA_F_WH
,
4669 v_dst
, v_src1
, v_src2
));
4670 set_MIPS_rounding_default_MSA(env
);
4674 case Iop_Div64Fx2
: {
4675 HReg v_dst
= newVRegV(env
);
4676 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4677 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4678 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4680 MIPSInstr_Msa3RF(MSA_FDIV
, MSA_F_DW
,
4681 v_dst
, v_src1
, v_src2
));
4682 set_MIPS_rounding_default_MSA(env
);
4686 case Iop_F32x4_2toQ16x8
: {
4687 HReg v_dst
= newVRegV(env
);
4688 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4689 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4690 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4692 MIPSInstr_Msa3RF(MSA_FTQ
, MSA_F_WH
,
4693 v_dst
, v_src1
, v_src2
));
4694 set_MIPS_rounding_default_MSA(env
);
4698 case Iop_F64x2_2toQ32x4
: {
4699 HReg v_dst
= newVRegV(env
);
4700 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4701 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4702 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4704 MIPSInstr_Msa3RF(MSA_FTQ
, MSA_F_DW
,
4705 v_dst
, v_src1
, v_src2
));
4706 set_MIPS_rounding_default_MSA(env
);
4710 case Iop_Scale2_32Fx4
: {
4711 HReg v_dst
= newVRegV(env
);
4712 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4713 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4714 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4716 MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_WH
,
4717 v_dst
, v_src1
, v_src2
));
4718 set_MIPS_rounding_default_MSA(env
);
4722 case Iop_Scale2_64Fx2
: {
4723 HReg v_dst
= newVRegV(env
);
4724 HReg v_src1
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg2
);
4725 HReg v_src2
= iselV128Expr(env
, e
->Iex
.Triop
.details
->arg3
);
4726 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
4728 MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
,
4729 v_dst
, v_src1
, v_src2
));
4730 set_MIPS_rounding_default_MSA(env
);
4735 vex_printf("iselV128Expr_wrk: unsupported triop: %x\n", op_triop
);
4739 if (e
->tag
== Iex_Const
) {
4740 IRConst
*con
= e
->Iex
.Const
.con
;
4742 if (con
->tag
!= Ico_V128
) {
4743 vpanic("iselV128Expr.const(mips)");
4745 HReg v_dst
= newVRegV(env
);
4746 UShort val
= con
->Ico
.V128
;
4747 HReg zero
= Zero(mode64
);
4750 case 0: /* likely */
4751 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, zero
, v_dst
));
4755 HReg r_tmp
= newVRegI(env
);
4757 addInstr(env
, MIPSInstr_LI(r_tmp
, 0xfful
));
4761 MIPSInstr_Msa2R(MSA_FILL
, MSA_B
, r_tmp
, v_dst
));
4764 MIPSInstr_Msa2R(MSA_FILL
, MSA_B
, zero
, v_dst
));
4767 for (i
= 1; i
< 16; i
++) {
4772 MIPSInstr_MsaElm(MSA_INSERT
, r_tmp
, v_dst
,
4776 MIPSInstr_MsaElm(MSA_INSERT
, zero
, v_dst
,
4789 if (e
->tag
== Iex_ITE
) {
4790 HReg v_dst
= newVRegV(env
);
4791 HReg iff
= iselV128Expr(env
, e
->Iex
.ITE
.iffalse
);
4792 HReg ift
= iselV128Expr(env
, e
->Iex
.ITE
.iftrue
);
4793 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
4794 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_cond
, r_cond
,
4795 MIPSRH_Imm(False
, 1)));
4796 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_cond
, v_dst
));
4798 MIPSInstr_Alu(Malu_ADD
, r_cond
, r_cond
, MIPSRH_Imm(True
, 1)));
4799 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_cond
, v_dst
, MSA_DFN_W
| 2));
4800 addInstr(env
, MIPSInstr_Msa3R(MSA_VSHF
, MSA_D
, v_dst
, ift
, iff
));
4804 vex_printf("iselV128Expr_wrk: Unsupported tag: %x\n", e
->tag
);
4806 vpanic("iselV128Expr(mips)");
4809 /*---------------------------------------------------------*/
4810 /*--- ISEL: Integer expressions (128 bit) ---*/
4811 /*---------------------------------------------------------*/
4813 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
4814 which is returned as the first two parameters. As with
4815 iselWordExpr_R, these may be either real or virtual regs; in any
4816 case they must not be changed by subsequent code emitted by the
4819 static void iselInt128Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4821 vassert(env
->mode64
);
4822 iselInt128Expr_wrk(rHi
, rLo
, env
, e
);
4823 vassert(hregClass(*rHi
) == HRcGPR(env
->mode64
));
4824 vassert(hregIsVirtual(*rHi
));
4825 vassert(hregClass(*rLo
) == HRcGPR(env
->mode64
));
4826 vassert(hregIsVirtual(*rLo
));
4829 /* DO NOT CALL THIS DIRECTLY ! */
4830 static void iselInt128Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
,
4834 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I128
);
4836 /* read 128-bit IRTemp */
4837 if (e
->tag
== Iex_RdTmp
) {
4838 lookupIRTempPair(rHi
, rLo
, env
, e
->Iex
.RdTmp
.tmp
);
4842 /* --------- BINARY ops --------- */
4843 if (e
->tag
== Iex_Binop
) {
4844 switch (e
->Iex
.Binop
.op
) {
4845 /* 64 x 64 -> 128 multiply */
4848 HReg tLo
= newVRegI(env
);
4849 HReg tHi
= newVRegI(env
);
4850 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_MullS64
);
4851 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4852 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4853 #if (__mips_isa_rev >= 6)
4854 addInstr(env
, MIPSInstr_Mulr6(syned
, False
, True
,
4855 tLo
, r_srcL
, r_srcR
));
4856 addInstr(env
, MIPSInstr_Mulr6(syned
, False
, False
,
4857 tHi
, r_srcL
, r_srcR
));
4859 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
4860 addInstr(env
, MIPSInstr_Mfhi(tHi
));
4861 addInstr(env
, MIPSInstr_Mflo(tLo
));
4868 /* 64HLto128(e1,e2) */
4870 *rHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4871 *rLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4874 case Iop_DivModU64to64
:
4875 case Iop_DivModS64to64
: {
4876 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
4877 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
4878 HReg tLo
= newVRegI(env
);
4879 HReg tHi
= newVRegI(env
);
4880 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS64to64
);
4881 #if (__mips_isa_rev >= 6)
4882 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
4883 False
/*32bit or 64bit div */ ,
4885 tLo
, r_srcL
, r_srcR
));
4886 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
4887 False
/*32bit or 64bit div */ ,
4889 tHi
, r_srcL
, r_srcR
));
4891 addInstr(env
, MIPSInstr_Div(syned
, False
, r_srcL
, r_srcR
));
4892 addInstr(env
, MIPSInstr_Mfhi(tHi
));
4893 addInstr(env
, MIPSInstr_Mflo(tLo
));
4904 vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e
->tag
);
4906 vpanic("iselInt128Expr(mips64)");
4909 /*---------------------------------------------------------*/
4910 /*--- ISEL: Integer expressions (64 bit) ---*/
4911 /*---------------------------------------------------------*/
4913 /* 32-bit mode ONLY. Compute a 64-bit value into the register
4914 * pair HI, LO. HI and LO must not be changed by subsequent
4915 * code emitted by the caller. */
4917 static void iselInt64Expr(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4919 vassert(!env
->mode64
);
4920 iselInt64Expr_wrk(rHi
, rLo
, env
, e
);
4921 vassert(hregClass(*rHi
) == HRcInt32
);
4922 vassert(hregIsVirtual(*rHi
));
4923 vassert(hregClass(*rLo
) == HRcInt32
);
4924 vassert(hregIsVirtual(*rLo
));
4927 /* DO NOT CALL THIS DIRECTLY ! */
4928 static void iselInt64Expr_wrk(HReg
* rHi
, HReg
* rLo
, ISelEnv
* env
, IRExpr
* e
)
4931 vassert(typeOfIRExpr(env
->type_env
, e
) == Ity_I64
);
4933 /* read 64-bit IRTemp */
4934 if (e
->tag
== Iex_RdTmp
) {
4935 lookupIRTemp64(rHi
, rLo
, env
, e
->Iex
.RdTmp
.tmp
);
4939 if (e
->tag
== Iex_Load
) {
4940 HReg tLo
= newVRegI(env
);
4941 HReg tHi
= newVRegI(env
);
4942 HReg r_addr
= iselWordExpr_R(env
, e
->Iex
.Load
.addr
);
4943 addInstr(env
, MIPSInstr_Load(4, tHi
, MIPSAMode_IR(0, r_addr
), mode64
));
4944 addInstr(env
, MIPSInstr_Load(4, tLo
, MIPSAMode_IR(4, r_addr
), mode64
));
4950 /* 64-bit literal */
4951 if (e
->tag
== Iex_Const
) {
4952 ULong w64
= e
->Iex
.Const
.con
->Ico
.U64
;
4953 UInt wHi
= toUInt(w64
>> 32);
4954 UInt wLo
= toUInt(w64
);
4955 HReg tLo
= newVRegI(env
);
4956 HReg tHi
= newVRegI(env
);
4957 vassert(e
->Iex
.Const
.con
->tag
== Ico_U64
);
4960 /* Save a precious Int register in this special case. */
4961 addInstr(env
, MIPSInstr_LI(tLo
, (ULong
) wLo
));
4965 addInstr(env
, MIPSInstr_LI(tHi
, (ULong
) wHi
));
4966 addInstr(env
, MIPSInstr_LI(tLo
, (ULong
) wLo
));
4975 if (e
->tag
== Iex_Get
) {
4976 HReg tLo
= newVRegI(env
);
4977 HReg tHi
= newVRegI(env
);
4979 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
4980 GuestStatePointer(mode64
));
4981 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
4982 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeInt(am_addr
), mode64
));
4989 if (e
->tag
== Iex_ITE
) {
4990 vassert(typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
);
4991 HReg expr0Lo
, expr0Hi
;
4992 HReg expr1Lo
, expr1Hi
;
4993 HReg desLo
= newVRegI(env
);
4994 HReg desHi
= newVRegI(env
);
4995 HReg cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
4997 /* expr0Hi:expr0Lo = iffalse */
4998 /* expr1Hi:expr1Lo = iftrue */
4999 iselInt64Expr(&expr0Hi
, &expr0Lo
, env
, e
->Iex
.ITE
.iffalse
);
5000 iselInt64Expr(&expr1Hi
, &expr1Lo
, env
, e
->Iex
.ITE
.iftrue
);
5002 /* move desLo, expr0Lo
5003 * move desHi, expr0Hi
5004 * movn desLo, expr1Lo, cond
5005 * movn desHi, expr1Hi, cond */
5006 #if (__mips_isa_rev >= 6)
5008 HReg r_temp
= newVRegI(env
);
5009 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, desLo
, expr0Lo
, cond
));
5010 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, expr1Lo
, cond
));
5011 addInstr(env
, MIPSInstr_Alu(Malu_OR
, desLo
, desLo
, MIPSRH_Reg(r_temp
)));
5013 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, desHi
, expr0Hi
, cond
));
5014 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_temp
, expr1Hi
, cond
));
5015 addInstr(env
, MIPSInstr_Alu(Malu_OR
, desHi
, desHi
, MIPSRH_Reg(r_temp
)));
5018 addInstr(env
, mk_iMOVds_RR(desLo
, expr0Lo
));
5019 addInstr(env
, mk_iMOVds_RR(desHi
, expr0Hi
));
5020 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, desLo
, expr1Lo
, cond
));
5021 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, desHi
, expr1Hi
, cond
));
5029 if (e
->tag
== Iex_CCall
) {
5030 HReg r_dstH
= newVRegI(env
);
5031 HReg r_dstL
= newVRegI(env
);
5032 vassert(e
->Iex
.CCall
.retty
== Ity_I64
);
5034 /* Marshal args, do the call, clear stack. */
5036 RetLoc rloc
= mk_RetLoc_INVALID();
5037 doHelperCall(&addToSp
, &rloc
, env
, NULL
/*guard*/, e
->Iex
.CCall
.cee
,
5038 e
->Iex
.CCall
.retty
, e
->Iex
.CCall
.args
);
5040 vassert(is_sane_RetLoc(rloc
));
5041 vassert(rloc
.pri
== RLPri_2Int
);
5042 vassert(addToSp
== 0);
5043 addInstr(env
, mk_iMOVds_RR(r_dstL
, hregMIPS_GPR2(False
)));
5044 addInstr(env
, mk_iMOVds_RR(r_dstH
, hregMIPS_GPR3(False
)));
5050 /* --------- BINARY ops --------- */
5051 if (e
->tag
== Iex_Binop
) {
5052 IROp op_binop
= e
->Iex
.Binop
.op
;
5054 /* 32 x 32 -> 64 multiply */
5057 HReg xLo
, xHi
, yLo
, yHi
, carryBit
;
5059 HReg tHi
= newVRegI(env
);
5060 HReg tHi1
= newVRegI(env
);
5061 HReg tLo
= newVRegI(env
);
5063 carryBit
= newVRegI(env
);
5066 MIPSCondCode cc
= MIPScc_LO
;
5068 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5069 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5070 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5073 addInstr(env
, MIPSInstr_Cmp(False
, size32
, carryBit
, tLo
, xLo
, cc
));
5075 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi1
, xHi
, MIPSRH_Reg(yHi
)));
5076 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, tHi1
,
5077 MIPSRH_Reg(carryBit
)));
5084 HReg xLo
, xHi
, yLo
, yHi
, borrow
;
5086 MIPSCondCode cc
= MIPScc_LO
;
5088 HReg tHi
= newVRegI(env
);
5089 HReg tLo
= newVRegI(env
);
5091 borrow
= newVRegI(env
);
5093 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5094 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5096 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5098 /* Check if borrow is nedded. */
5099 addInstr(env
, MIPSInstr_Cmp(False
, size32
, borrow
, xLo
, yLo
, cc
));
5101 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, yHi
, yHi
,
5102 MIPSRH_Reg(borrow
)));
5103 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tHi
, xHi
, MIPSRH_Reg(yHi
)));
5111 HReg tLo
= newVRegI(env
);
5112 HReg tHi
= newVRegI(env
);
5113 Bool syned
= toBool(op_binop
== Iop_MullS32
);
5114 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5115 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5116 #if (__mips_isa_rev >= 6)
5117 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, True
,
5118 tLo
, r_srcL
, r_srcR
));
5119 addInstr(env
, MIPSInstr_Mulr6(syned
, True
, False
,
5120 tHi
, r_srcL
, r_srcR
));
5122 addInstr(env
, MIPSInstr_Mult(syned
, r_srcL
, r_srcR
));
5123 addInstr(env
, MIPSInstr_Mfhi(tHi
));
5124 addInstr(env
, MIPSInstr_Mflo(tLo
));
5132 case Iop_DivModU32to32
:
5133 case Iop_DivModS32to32
: {
5134 HReg r_srcL
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5135 HReg r_srcR
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5136 HReg tLo
= newVRegI(env
);
5137 HReg tHi
= newVRegI(env
);
5138 Bool syned
= toBool(e
->Iex
.Binop
.op
== Iop_DivModS32to32
);
5140 #if (__mips_isa_rev >= 6)
5141 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
5142 True
/*32bit or 64bit div */ ,
5144 tLo
, r_srcL
, r_srcR
));
5145 addInstr(env
, MIPSInstr_Divr6(syned
/*Unsigned or Signed */ ,
5146 True
/*32bit or 64bit div */ ,
5148 tHi
, r_srcL
, r_srcR
));
5150 addInstr(env
, MIPSInstr_Div(syned
, True
, r_srcL
, r_srcR
));
5151 addInstr(env
, MIPSInstr_Mfhi(tHi
));
5152 addInstr(env
, MIPSInstr_Mflo(tLo
));
5159 /* 32HLto64(e1,e2) */
5161 *rHi
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg1
);
5162 *rLo
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
5165 /* Or64/And64/Xor64 */
5169 HReg xLo
, xHi
, yLo
, yHi
;
5170 HReg tLo
= newVRegI(env
);
5171 HReg tHi
= newVRegI(env
);
5172 MIPSAluOp op
= (op_binop
== Iop_Or64
) ? Malu_OR
:
5173 (op_binop
== Iop_And64
) ? Malu_AND
: Malu_XOR
;
5174 iselInt64Expr(&xHi
, &xLo
, env
, e
->Iex
.Binop
.arg1
);
5175 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Binop
.arg2
);
5176 addInstr(env
, MIPSInstr_Alu(op
, tHi
, xHi
, MIPSRH_Reg(yHi
)));
5177 addInstr(env
, MIPSInstr_Alu(op
, tLo
, xLo
, MIPSRH_Reg(yLo
)));
5184 /* 64-bit logical shift right based on what gcc generates:
5197 HReg r_srcLo
, r_srcHi
;
5198 HReg r_srcLotmp
= newVRegI(env
);
5199 HReg shift
= newVRegI(env
);
5200 HReg a3
= newVRegI(env
);
5201 HReg r_dstLo
= newVRegI(env
);
5202 HReg r_dstHi
= newVRegI(env
);
5203 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5206 iselInt64Expr(&r_srcHi
, &r_srcLo
, env
, e
->Iex
.Binop
.arg1
);
5207 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5209 if (sa
->tag
== Mrh_Imm
) {
5210 addInstr(env
, MIPSInstr_LI(shift
, sa
->Mrh
.Imm
.imm16
));
5213 addInstr(env
, MIPSInstr_Alu(Malu_AND
, shift
, sa
->Mrh
.Reg
.reg
,
5214 MIPSRH_Imm(False
, 0x3f)));
5216 /* nor r_dstLo, zero, shift */
5217 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(shift
)));
5218 /* sll a3, r_srcHi, 0x1 */
5219 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5220 a3
, r_srcHi
, MIPSRH_Imm(False
, 0x1)));
5221 /* sllv a3, a3, r_dstLo */
5222 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5223 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5224 /* srlv r_dstLo, r_srcLo, shift */
5225 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5226 r_dstLo
, r_srcLo
, MIPSRH_Reg(shift
)));
5227 /* srlv r_dstHi, r_srcHi, shift */
5228 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5229 r_dstHi
, r_srcHi
, MIPSRH_Reg(shift
)));
5230 /* andi r_srcLo, shift, 0x20 */
5231 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcLotmp
, shift
,
5232 MIPSRH_Imm(False
, 0x20)));
5233 /* or r_dstLo, a3, r_dstLo */
5234 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, a3
, MIPSRH_Reg(r_dstLo
)));
5235 #if (__mips_isa_rev >= 6)
5236 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, r_srcLotmp
));
5237 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_dstHi
, r_srcLotmp
));
5238 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, r_dstLo
, MIPSRH_Reg(a3
)));
5240 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, r_srcLotmp
));
5242 /* movn r_dstLo, r_dstHi, r_srcLo */
5243 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, r_dstHi
, r_srcLotmp
));
5244 /* movn r_dstHi, zero, r_srcLo */
5245 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, zero
, r_srcLotmp
));
5253 /* 64-bit shift left based on what gcc generates:
5267 HReg r_srcLo
, r_srcHi
;
5268 HReg r_shift
= newVRegI(env
);
5269 HReg a3
= newVRegI(env
);
5270 HReg r_dstLo
= newVRegI(env
);
5271 HReg r_dstHi
= newVRegI(env
);
5272 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5275 iselInt64Expr(&r_srcHi
, &r_srcLo
, env
, e
->Iex
.Binop
.arg1
);
5276 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5278 if (sa
->tag
== Mrh_Imm
) {
5279 addInstr(env
, MIPSInstr_LI(r_shift
, sa
->Mrh
.Imm
.imm16
));
5282 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_shift
, sa
->Mrh
.Reg
.reg
,
5283 MIPSRH_Imm(False
, 0x3f)));
5285 /* nor r_dstLo, zero, r_shift */
5286 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(r_shift
)));
5287 /* srl a3, r_srcLo, 0x1 */
5288 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5289 a3
, r_srcLo
, MIPSRH_Imm(False
, 0x1)));
5290 /* srlv a3, a3, r_dstLo */
5291 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5292 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5293 /* sllv r_dstHi, r_srcHi, r_shift */
5294 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5295 r_dstHi
, r_srcHi
, MIPSRH_Reg(r_shift
)));
5296 /* or r_dstHi, a3, r_dstHi */
5297 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, a3
, MIPSRH_Reg(r_dstHi
)));
5298 /* andi a3, r_shift, 0x20 */
5299 addInstr(env
, MIPSInstr_Alu(Malu_AND
, a3
, r_shift
,
5300 MIPSRH_Imm(False
, 0x20)));
5301 /* sllv r_dstLo, r_srcLo, r_shift */
5302 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5303 r_dstLo
, r_srcLo
, MIPSRH_Reg(r_shift
)));
5304 #if (__mips_isa_rev >= 6)
5305 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, a3
));
5306 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, r_shift
, r_dstLo
, a3
));
5307 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, r_dstHi
, MIPSRH_Reg(r_shift
)));
5309 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, a3
));
5311 /* movn r_dstHi, r_dstLo, a3 */
5312 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, r_dstLo
, a3
));
5313 /* movn r_dstLo, zero, a3 */
5314 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, zero
, a3
));
5322 /* 64-bit arithmetic shift right based on what gcc generates:
5336 HReg r_srcHi
, r_srcLo
;
5337 HReg r_srcHitmp
= newVRegI(env
);
5338 HReg r_srcLotmp
= newVRegI(env
);
5339 HReg r_shift
= newVRegI(env
);
5340 HReg a3
= newVRegI(env
);
5341 HReg r_dstLo
= newVRegI(env
);
5342 HReg r_dstHi
= newVRegI(env
);
5343 HReg zero
= hregMIPS_GPR0(env
->mode64
);
5346 iselInt64Expr(&r_srcLo
, &r_srcHi
, env
, e
->Iex
.Binop
.arg1
);
5347 sa
= iselWordExpr_RH6u(env
, e
->Iex
.Binop
.arg2
);
5349 if (sa
->tag
== Mrh_Imm
) {
5350 addInstr(env
, MIPSInstr_LI(r_shift
, sa
->Mrh
.Imm
.imm16
));
5353 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_shift
, sa
->Mrh
.Reg
.reg
,
5354 MIPSRH_Imm(False
, 0x3f)));
5356 /* nor r_dstLo, zero, r_shift */
5357 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, r_dstLo
, zero
, MIPSRH_Reg(r_shift
)));
5358 /* sll a3, r_srcLo, 0x1 */
5359 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5360 a3
, r_srcLo
, MIPSRH_Imm(False
, 0x1)));
5361 /* sllv a3, a3, r_dstLo */
5362 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
/* 32bit shift */,
5363 a3
, a3
, MIPSRH_Reg(r_dstLo
)));
5364 /* srlv r_dstLo, r_srcHi, r_shift */
5365 addInstr(env
, MIPSInstr_Shft(Mshft_SRL
, True
/* 32bit shift */,
5366 r_dstLo
, r_srcHi
, MIPSRH_Reg(r_shift
)));
5367 /* srav r_dstHi, r_srcLo, r_shift */
5368 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
/* 32bit shift */,
5369 r_dstHi
, r_srcLo
, MIPSRH_Reg(r_shift
)));
5370 /* andi r_srcHi, r_shift, 0x20 */
5371 addInstr(env
, MIPSInstr_Alu(Malu_AND
, r_srcHitmp
, r_shift
,
5372 MIPSRH_Imm(False
, 0x20)));
5373 /* sra r_srcLo, r_srcLo, 0x1f */
5374 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
/* 32bit shift */,
5375 r_srcLotmp
, r_srcLo
, MIPSRH_Imm(False
, 0x1f)));
5376 /* or r_dstLo, a3, r_dstLo */
5377 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, a3
, MIPSRH_Reg(r_dstLo
)));
5378 #if (__mips_isa_rev >= 6)
5379 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstLo
, r_dstLo
, r_srcHitmp
));
5380 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_dstHi
, r_srcHitmp
));
5381 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstLo
, r_dstLo
, MIPSRH_Reg(a3
)));
5383 addInstr(env
, MIPSInstr_MoveCond(MSeleqz
, r_dstHi
, r_dstHi
, r_srcHitmp
));
5384 addInstr(env
, MIPSInstr_MoveCond(MSelnez
, a3
, r_srcLotmp
, r_srcHitmp
));
5385 addInstr(env
, MIPSInstr_Alu(Malu_OR
, r_dstHi
, r_dstHi
, MIPSRH_Reg(a3
)));
5387 /* movn r_dstLo, r_dstHi, r_srcHi */
5388 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstLo
, r_dstHi
, r_srcHitmp
));
5389 /* movn r_dstHi, r_srcLo, r_srcHi */
5390 addInstr(env
, MIPSInstr_MoveCond(MMoveCond_movn
, r_dstHi
, r_srcLotmp
, r_srcHitmp
));
5397 case Iop_F32toI64S
: {
5398 HReg tmpD
= newVRegD(env
);
5399 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
5400 HReg tLo
= newVRegI(env
);
5401 HReg tHi
= newVRegI(env
);
5404 /* CVTLS tmpD, valF */
5405 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
5406 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLS
, tmpD
, valF
));
5407 set_MIPS_rounding_default(env
);
5409 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5410 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5413 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
5416 #if defined (_MIPSEL)
5417 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5418 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5420 #elif defined (_MIPSEB)
5421 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5422 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5434 case Iop_F64toI64U
: {
5436 HReg tmp
= newVRegV(env
);
5438 r_src
= iselDblExpr( env
, e
->Iex
.Binop
.arg2
);
5439 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
5440 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_U
, MSA_F_DW
, tmp
, r_src
));
5441 HReg r_dsth
= newVRegI(env
);
5442 HReg r_dstl
= newVRegI(env
);
5444 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dstl
, MSA_DFN_W
| 0));
5446 MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_dsth
, MSA_DFN_W
| 1));
5449 set_MIPS_rounding_default_MSA(env
);
5453 case Iop_GetElem64x2
: {
5455 HReg v_src
= iselV128Expr(env
, e
->Iex
.Binop
.arg1
);
5456 HReg r_dstHI
= newVRegI(env
);
5457 HReg r_dstLO
= newVRegI(env
);
5458 MIPSRH
*tmp
= iselWordExpr_RH(env
, False
, e
->Iex
.Binop
.arg2
);
5463 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dstHI
,
5465 (((tmp
->Mrh
.Imm
.imm16
& 0x01) << 1)
5468 MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, r_dstLO
,
5470 ((tmp
->Mrh
.Imm
.imm16
& 0x01) << 1)));
5474 HReg v_tmp
= newVRegV(env
);
5476 MIPSInstr_Msa3R(MSA_SPLAT
, MSA_D
, v_tmp
, v_src
,
5479 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dstHI
,
5482 MIPSInstr_MsaElm(MSA_COPY_S
, v_tmp
, r_dstLO
,
5494 HReg a_L
, a_H
, b_L
, b_H
;
5495 HReg dst_L
= newVRegI(env
);
5496 HReg dst_H
= newVRegI(env
);
5498 iselInt64Expr(&a_H
, &a_L
, env
, e
->Iex
.Binop
.arg1
);
5499 iselInt64Expr(&b_H
, &b_L
, env
, e
->Iex
.Binop
.arg2
);
5500 #if (__mips_isa_rev >= 6)
5501 addInstr(env
, MIPSInstr_Mulr6(True
, True
, True
,
5503 addInstr(env
, MIPSInstr_Mulr6(True
, True
, True
,
5505 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5506 MIPSRH_Reg(dst_L
)));
5507 addInstr(env
, MIPSInstr_Mulr6(False
, True
, False
,
5510 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5511 MIPSRH_Reg(dst_L
)));
5512 addInstr(env
, MIPSInstr_Mulr6(False
, True
, True
,
5515 addInstr(env
, MIPSInstr_Mul(dst_H
, a_H
, b_L
));
5516 addInstr(env
, MIPSInstr_Mult(True
, b_H
, a_L
));
5517 addInstr(env
, MIPSInstr_Mflo(dst_L
));
5518 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5519 MIPSRH_Reg(dst_L
)));
5520 addInstr(env
, MIPSInstr_Mult(False
, a_L
, b_L
));
5521 addInstr(env
, MIPSInstr_Mfhi(dst_L
));
5523 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, dst_H
, dst_H
,
5524 MIPSRH_Reg(dst_L
)));
5525 addInstr(env
, MIPSInstr_Mflo(dst_L
));
5533 HReg src1_L
, src1_H
, src2_L
, src2_H
;
5534 HReg dst_L
= newVRegI(env
);
5535 HReg dst_H
= newVRegI(env
);
5536 HReg tmp1
= newVRegV(env
);
5537 HReg tmp2
= newVRegV(env
);
5539 iselInt64Expr(&src1_H
, &src1_L
, env
, e
->Iex
.Binop
.arg1
);
5540 iselInt64Expr(&src2_H
, &src2_L
, env
, e
->Iex
.Binop
.arg2
);
5541 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src1_L
, tmp1
));
5542 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src1_H
, tmp1
, MSA_DFN_W
| 1));
5543 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src2_L
, tmp2
));
5544 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src2_H
, tmp2
, MSA_DFN_W
| 1));
5545 addInstr(env
, MIPSInstr_Msa3R(MSA_DIVS
, MSA_D
, tmp1
, tmp1
, tmp2
));
5546 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_H
, MSA_DFN_W
| 1));
5547 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_L
, MSA_DFN_W
| 0));
5554 HReg src1_L
, src1_H
, src2_L
, src2_H
;
5555 HReg dst_L
= newVRegI(env
);
5556 HReg dst_H
= newVRegI(env
);
5557 HReg tmp1
= newVRegV(env
);
5558 HReg tmp2
= newVRegV(env
);
5560 iselInt64Expr(&src1_H
, &src1_L
, env
, e
->Iex
.Binop
.arg1
);
5561 iselInt64Expr(&src2_H
, &src2_L
, env
, e
->Iex
.Binop
.arg2
);
5562 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src1_L
, tmp1
));
5563 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src1_H
, tmp1
, MSA_DFN_W
| 1));
5564 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, src2_L
, tmp2
));
5565 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, src2_H
, tmp2
, MSA_DFN_W
| 1));
5566 addInstr(env
, MIPSInstr_Msa3R(MSA_DIVU
, MSA_D
, tmp1
, tmp1
, tmp2
));
5567 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_H
, MSA_DFN_W
| 1));
5568 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp1
, dst_L
, MSA_DFN_W
| 0));
5574 case Iop_F64toI64S
: {
5575 HReg tmpD
= newVRegD(env
);
5577 HReg tLo
= newVRegI(env
);
5578 HReg tHi
= newVRegI(env
);
5582 valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
5584 valF
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
5587 /* CVTLS tmpD, valF */
5588 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
5589 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, tmpD
, valF
));
5590 set_MIPS_rounding_default(env
);
5592 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5593 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5596 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, tmpD
,
5599 #if defined (_MIPSEL)
5600 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5601 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5603 #elif defined (_MIPSEB)
5604 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5605 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5623 /* --------- UNARY ops --------- */
5624 if (e
->tag
== Iex_Unop
) {
5625 switch (e
->Iex
.Unop
.op
) {
5627 HReg tLo
= newVRegI(env
);
5628 HReg tHi
= newVRegI(env
);
5629 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5630 HReg tmp
= newVRegI(env
);
5632 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tmp
, src
,
5633 MIPSRH_Imm(False
, 31)));
5634 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tmp
, tmp
,
5635 MIPSRH_Imm(False
, 31)));
5637 addInstr(env
, mk_iMOVds_RR(tHi
, tmp
));
5638 addInstr(env
, mk_iMOVds_RR(tLo
, tmp
));
5647 HReg tLo
= newVRegI(env
);
5648 HReg tHi
= newVRegI(env
);
5649 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5650 UInt no_bits
= (e
->Iex
.Unop
.op
== Iop_8Sto64
) ? 24 : 16;
5651 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5652 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, tLo
, tLo
,
5653 MIPSRH_Imm(False
, no_bits
)));
5654 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tHi
, tLo
,
5655 MIPSRH_Imm(False
, 31)));
5656 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tLo
, tLo
,
5657 MIPSRH_Imm(False
, no_bits
)));
5658 addInstr(env
, mk_iMOVds_RR(tHi
, tLo
));
5666 HReg tLo
= newVRegI(env
);
5667 HReg tHi
= newVRegI(env
);
5668 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5669 addInstr(env
, mk_iMOVds_RR(tHi
, src
));
5670 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5671 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tHi
, tHi
,
5672 MIPSRH_Imm(False
, 31)));
5680 HReg tLo
= newVRegI(env
);
5681 HReg tHi
= newVRegI(env
);
5682 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5683 UInt mask
= (e
->Iex
.Unop
.op
== Iop_8Sto64
) ? 0xFF : 0xFFFF;
5684 addInstr(env
, MIPSInstr_Alu(Malu_AND
, tLo
, src
,
5685 MIPSRH_Imm(False
, mask
)));
5686 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, hregMIPS_GPR0(mode64
),
5687 MIPSRH_Reg(hregMIPS_GPR0(mode64
))));
5695 HReg tLo
= newVRegI(env
);
5696 HReg tHi
= newVRegI(env
);
5697 HReg src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5698 addInstr(env
, mk_iMOVds_RR(tLo
, src
));
5699 addInstr(env
, MIPSInstr_Alu(Malu_ADD
, tHi
, hregMIPS_GPR0(mode64
),
5700 MIPSRH_Reg(hregMIPS_GPR0(mode64
))));
5708 HReg tHi
= newVRegI(env
);
5709 HReg tLo
= newVRegI(env
);
5710 HReg tmp
= newVRegI(env
);
5711 HReg tmp1
= newVRegI(env
);
5712 HReg tmp2
= newVRegI(env
);
5713 HReg zero
= newVRegI(env
);
5714 MIPSCondCode cc
= MIPScc_LO
;
5717 iselInt64Expr(&yHi
, &yLo
, env
, e
->Iex
.Unop
.arg
);
5719 addInstr(env
, MIPSInstr_LI(zero
, 0x00000000));
5721 /* tmp2:tmp1 = 0 - (yHi:yLo)*/
5722 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp2
, zero
, MIPSRH_Reg(yLo
)));
5723 addInstr(env
, MIPSInstr_Cmp(False
, True
, tmp1
, zero
, tmp2
, cc
));
5724 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp
, zero
, MIPSRH_Reg(yHi
)));
5725 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp1
, tmp
, MIPSRH_Reg(tmp1
)));
5727 /* So now we have tmp2:tmp1 = -arg. To finish off, or 'arg'
5728 back in, so as to give the final result
5729 tHi:tLo = arg | -arg. */
5730 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tHi
, yHi
, MIPSRH_Reg(tmp1
)));
5731 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tLo
, yLo
, MIPSRH_Reg(tmp2
)));
5737 case Iop_CmpwNEZ64
: {
5739 HReg tmp1
= newVRegI(env
);
5740 HReg tmp2
= newVRegI(env
);
5741 /* srcHi:srcLo = arg */
5742 iselInt64Expr(&srcHi
, &srcLo
, env
, e
->Iex
.Unop
.arg
);
5743 /* tmp1 = srcHi | srcLo */
5744 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp1
, srcLo
,
5745 MIPSRH_Reg(srcHi
)));
5746 /* tmp2 = (tmp1 | -tmp1) >>s 31 */
5748 addInstr(env
, MIPSInstr_Alu(Malu_SUB
, tmp2
, hregMIPS_GPR0(mode64
),
5751 addInstr(env
, MIPSInstr_Alu(Malu_OR
, tmp2
, tmp2
, MIPSRH_Reg(tmp1
)));
5752 addInstr(env
, MIPSInstr_Shft(Mshft_SRA
, True
, tmp2
, tmp2
,
5753 MIPSRH_Imm(False
, 31)));
5759 case Iop_ReinterpF64asI64
: {
5760 HReg tLo
= newVRegI(env
);
5761 HReg tHi
= newVRegI(env
);
5763 HReg fr_src
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
5765 sub_from_sp(env
, 16); /* Move SP down 16 bytes */
5766 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
5769 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
5772 #if defined (_MIPSEL)
5773 addInstr(env
, MIPSInstr_Load(4, tLo
, am_addr
, mode64
));
5774 addInstr(env
, MIPSInstr_Load(4, tHi
, nextMIPSAModeFloat(am_addr
),
5776 #elif defined (_MIPSEB)
5777 addInstr(env
, MIPSInstr_Load(4, tHi
, am_addr
, mode64
));
5778 addInstr(env
, MIPSInstr_Load(4, tLo
, nextMIPSAModeFloat(am_addr
),
5791 HReg tLo
= newVRegI(env
);
5792 HReg tHi
= newVRegI(env
);
5793 iselInt64Expr(&tHi
, &tLo
, env
, e
->Iex
.Unop
.arg
);
5794 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tLo
, tLo
, MIPSRH_Reg(tLo
)));
5795 addInstr(env
, MIPSInstr_Alu(Malu_NOR
, tHi
, tHi
, MIPSRH_Reg(tHi
)));
5802 case Iop_V128HIto64
: {
5804 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5805 HReg tLo
= newVRegI(env
);
5806 HReg tHi
= newVRegI(env
);
5807 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 2));
5808 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 3));
5814 case Iop_V128to64
: {
5816 HReg v_src
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5817 HReg tLo
= newVRegI(env
);
5818 HReg tHi
= newVRegI(env
);
5819 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 0));
5820 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 1));
5826 case Iop_F32toF16x4_DEP
: {
5828 HReg v_arg
= iselV128Expr(env
, e
->Iex
.Unop
.arg
);
5829 HReg v_src
= newVRegV(env
);
5830 set_guest_MIPS_rounding_mode_MSA(env
);
5831 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXDO
, MSA_F_WH
, v_src
, v_arg
, v_arg
));
5832 set_MIPS_rounding_default_MSA(env
);
5833 HReg tLo
= newVRegI(env
);
5834 HReg tHi
= newVRegI(env
);
5835 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tLo
, MSA_DFN_W
| 0));
5836 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, v_src
, tHi
, MSA_DFN_W
| 1));
5843 vex_printf("UNARY: No such op: ");
5844 ppIROp(e
->Iex
.Unop
.op
);
5850 vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e
->tag
);
5852 vpanic("iselInt64Expr(mips)");
5855 /*---------------------------------------------------------*/
5856 /*--- ISEL: Floating point expressions (32 bit) ---*/
5857 /*---------------------------------------------------------*/
5859 /* Nothing interesting here; really just wrappers for
5861 static HReg
iselFltExpr(ISelEnv
* env
, IRExpr
* e
)
5864 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
5865 if (ty
== Ity_F32
|| (ty
== Ity_F64
&& fp_mode64
)) {
5866 r
= iselFltExpr_wrk(env
, e
);
5868 r
= iselDblExpr_wrk(env
, e
);
5869 vassert(hregClass(r
) == HRcFlt64
);
5874 /* DO NOT CALL THIS DIRECTLY */
5875 static HReg
iselFltExpr_wrk(ISelEnv
* env
, IRExpr
* e
)
5877 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
5878 vassert(ty
== Ity_F32
|| (ty
== Ity_F64
&& fp_mode64
));
5880 if (e
->tag
== Iex_RdTmp
) {
5881 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
5884 if (e
->tag
== Iex_Load
) {
5885 vassert(e
->Iex
.Load
.ty
== Ity_F32
5886 || (e
->Iex
.Load
.ty
== Ity_F64
&& fp_mode64
));
5888 MIPSAMode
*am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
5889 if (e
->Iex
.Load
.ty
== Ity_F64
) {
5890 r_dst
= newVRegD(env
);
5891 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
5893 r_dst
= newVRegF(env
);
5894 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 4, r_dst
, am_addr
));
5899 if (e
->tag
== Iex_Get
) {
5900 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
5901 GuestStatePointer(mode64
));
5903 if (e
->Iex
.Load
.ty
== Ity_F64
) {
5904 r_dst
= newVRegD(env
);
5905 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
5907 r_dst
= newVRegF(env
);
5908 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 4, r_dst
, am_addr
));
5913 if (e
->tag
== Iex_Unop
) {
5914 switch (e
->Iex
.Unop
.op
) {
5915 case Iop_ReinterpI32asF32
: {
5916 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5917 HReg r_dst
= newVRegF(env
);
5919 /* Move Word to Floating Point
5921 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, fr_src
));
5925 case Iop_F32toF64
: {
5927 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5928 HReg dst
= newVRegD(env
);
5930 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDS
, dst
, src
));
5933 case Iop_ReinterpI64asF64
: {
5936 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5937 r_dst
= newVRegF(env
);
5938 /* Move Doubleword to Floating Point
5939 dmtc1 r_dst, fr_src */
5940 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_dmtc1
, r_dst
, fr_src
));
5943 r_dst
= newVRegD(env
);
5944 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Unop
.arg
);
5945 r_dst
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
5949 case Iop_I32StoF64
: {
5951 HReg dst
= newVRegF(env
);
5952 HReg tmp
= newVRegF(env
);
5953 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
5955 /* Move Word to Floating Point
5957 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, r_src
));
5959 /* and do convert */
5960 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDW
, dst
, tmp
));
5966 Bool sz32
= e
->Iex
.Unop
.op
== Iop_AbsF32
;
5967 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5968 HReg dst
= newVRegF(env
);
5969 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_ABSS
: Mfp_ABSD
, dst
, src
));
5974 Bool sz32
= e
->Iex
.Unop
.op
== Iop_NegF32
;
5975 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5976 HReg dst
= newVRegF(env
);
5977 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_NEGS
: Mfp_NEGD
, dst
, src
));
5980 case Iop_RoundF64toF64_ZERO
: {
5982 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5983 HReg dst
= newVRegF(env
);
5984 addInstr(env
, MIPSInstr_FpConvert(Mfp_TRULD
, dst
, src
));
5987 case Iop_RoundF64toF64_NEAREST
: {
5989 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5990 HReg dst
= newVRegF(env
);
5991 addInstr(env
, MIPSInstr_FpConvert(Mfp_ROUNDLD
, dst
, src
));
5994 case Iop_RoundF64toF64_NegINF
: {
5996 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
5997 HReg dst
= newVRegF(env
);
5998 addInstr(env
, MIPSInstr_FpConvert(Mfp_FLOORLD
, dst
, src
));
6001 case Iop_RoundF64toF64_PosINF
: {
6003 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6004 HReg dst
= newVRegF(env
);
6005 addInstr(env
, MIPSInstr_FpConvert(Mfp_CEILLD
, dst
, src
));
6014 if (e
->tag
== Iex_Triop
) {
6015 switch (e
->Iex
.Triop
.details
->op
) {
6025 HReg argL
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6026 HReg argR
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6027 HReg dst
= newVRegF(env
);
6028 switch (e
->Iex
.Triop
.details
->op
) {
6060 set_MIPS_rounding_mode(env
, e
->Iex
.Triop
.details
->arg1
);
6061 addInstr(env
, MIPSInstr_FpBinary(op
, dst
, argL
, argR
));
6062 set_MIPS_rounding_default(env
);
6065 case Iop_ScaleF64
: {
6066 HReg src1
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6067 HReg src2
= iselFltExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6068 HReg v_help
= newVRegV(env
);
6069 HReg dst
= newVRegF(env
);
6071 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
6072 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_S
, MSA_F_DW
, v_help
, src2
));
6073 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
, dst
, src1
, v_help
));
6074 set_MIPS_rounding_default_MSA(env
);
6083 if (e
->tag
== Iex_Binop
) {
6084 switch (e
->Iex
.Binop
.op
) {
6085 case Iop_F64toF32
: {
6088 valD
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6090 valD
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6091 HReg valS
= newVRegF(env
);
6093 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6094 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSD
, valS
, valD
));
6095 set_MIPS_rounding_default(env
);
6099 case Iop_RoundF32toInt
: {
6100 HReg valS
= newVRegF(env
);
6101 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6103 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6104 #if (__mips_isa_rev >= 6)
6105 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTS
, valS
, valF
));
6107 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTWS
, valS
, valF
));
6108 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSW
, valS
, valS
));
6110 set_MIPS_rounding_default(env
);
6114 case Iop_RoundF64toInt
: {
6115 HReg valS
= newVRegF(env
);
6116 HReg valF
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6118 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6119 #if (__mips_isa_rev >= 6)
6120 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTD
, valS
, valF
));
6122 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, valS
, valF
));
6123 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, valS
, valS
));
6126 set_MIPS_rounding_default(env
);
6130 case Iop_I32StoF32
: {
6131 HReg r_dst
= newVRegF(env
);
6132 HReg fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6133 HReg tmp
= newVRegF(env
);
6135 /* Move Word to Floating Point
6137 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, fr_src
));
6139 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6140 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSW
, r_dst
, tmp
));
6141 set_MIPS_rounding_default(env
);
6146 case Iop_I64StoF64
: {
6147 HReg r_dst
= newVRegF(env
);
6151 tmp
= newVRegF(env
);
6152 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6153 /* Move SP down 8 bytes */
6154 sub_from_sp(env
, 8);
6155 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6158 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6160 /* load as Ity_F64 */
6161 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6167 tmp
= newVRegD(env
);
6168 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6169 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6172 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6173 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6174 set_MIPS_rounding_default(env
);
6179 case Iop_I64StoF32
: {
6180 HReg r_dst
= newVRegF(env
);
6184 tmp
= newVRegF(env
);
6185 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6186 /* Move SP down 8 bytes */
6187 sub_from_sp(env
, 8);
6188 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6191 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6193 /* load as Ity_F64 */
6194 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6200 tmp
= newVRegD(env
);
6201 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6202 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6205 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6206 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTSL
, r_dst
, tmp
));
6207 set_MIPS_rounding_default(env
);
6214 Bool sz32
= e
->Iex
.Binop
.op
== Iop_SqrtF32
;
6215 HReg src
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6216 HReg dst
= newVRegF(env
);
6217 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6218 addInstr(env
, MIPSInstr_FpUnary(sz32
? Mfp_SQRTS
: Mfp_SQRTD
, dst
,
6220 set_MIPS_rounding_default(env
);
6224 case Iop_I64UtoF64
: {
6226 HReg r_dst
= newVRegF(env
);
6227 HReg tmp
= newVRegV(env
);
6230 r_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6231 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
6232 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_D
, r_src
, tmp
));
6233 HReg r_srch
= newVRegI(env
);
6234 addInstr(env
, MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_DW
, tmp
, tmp
));
6235 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srch
, MSA_DFN_D
| 0));
6236 sub_from_sp(env
, 8);
6237 MIPSAMode
*am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6240 addInstr(env
, MIPSInstr_Store(8, am_addr
, r_srch
, mode64
));
6242 /* load as Ity_F64 */
6243 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, r_dst
, am_addr
));
6247 set_MIPS_rounding_default_MSA(env
);
6251 #if (__mips_isa_rev >= 6)
6252 case Iop_MaxNumF32
: {
6253 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6254 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6255 HReg dst
= newVRegF(env
);
6256 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXS
, dst
,
6261 case Iop_MaxNumF64
: {
6262 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6263 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6264 HReg dst
= newVRegF(env
);
6265 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXD
, dst
,
6270 case Iop_MinNumF32
: {
6271 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6272 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6273 HReg dst
= newVRegF(env
);
6274 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MINS
, dst
,
6279 case Iop_MinNumF64
: {
6280 HReg src1
= iselFltExpr(env
, e
->Iex
.Binop
.arg1
);
6281 HReg src2
= iselFltExpr(env
, e
->Iex
.Binop
.arg2
);
6282 HReg dst
= newVRegF(env
);
6283 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MIND
, dst
,
6293 if (e
->tag
== Iex_Qop
) {
6294 switch (e
->Iex
.Qop
.details
->op
) {
6300 #if (__mips_isa_rev < 6)
6303 switch (e
->Iex
.Qop
.details
->op
) {
6304 #if (__mips_isa_rev >= 6)
6319 op
= has_msa
? MSA_FMADD
: Mfp_MADDS
;
6323 op
= has_msa
? MSA_FMADD
: Mfp_MADDD
;
6327 op
= has_msa
? MSA_FMSUB
: Mfp_MSUBS
;
6331 op
= has_msa
? MSA_FMSUB
: Mfp_MSUBD
;
6339 HReg dst
= newVRegF(env
);
6340 HReg src1
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg2
);
6341 HReg src2
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg3
);
6342 HReg src3
= iselFltExpr(env
, e
->Iex
.Qop
.details
->arg4
);
6343 #if (__mips_isa_rev >= 6)
6344 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6345 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6347 set_MIPS_rounding_default(env
);
6350 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, src3
, dst
, 0));
6351 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Qop
.details
->arg1
);
6352 addInstr(env
, MIPSInstr_Msa3RF(op
, type
, dst
, src1
, src2
));
6353 set_MIPS_rounding_default_MSA(env
);
6355 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6356 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6358 set_MIPS_rounding_default(env
);
6369 if (e
->tag
== Iex_Unop
&& e
->Iex
.Unop
.op
== Iop_TruncF64asF32
) {
6370 /* This is quite subtle. The only way to do the relevant
6371 truncation is to do a single-precision store and then a
6372 double precision load to get it back into a register. The
6373 problem is, if the data is then written to memory a second
6376 STbe(...) = TruncF64asF32(...)
6378 then will the second truncation further alter the value? The
6379 answer is no: flds (as generated here) followed by fsts
6380 (generated for the STbe) is the identity function on 32-bit
6381 floats, so we are safe.
6383 Another upshot of this is that if iselStmt can see the
6386 STbe(...) = TruncF64asF32(arg)
6388 then it can short circuit having to deal with TruncF64asF32
6389 individually; instead just compute arg into a 64-bit FP
6390 register and do 'fsts' (since that itself does the
6393 We generate pretty poor code here (should be ok both for
6394 32-bit and 64-bit mode); but it is expected that for the most
6395 part the latter optimisation will apply and hence this code
6396 will not often be used.
6398 HReg fsrc
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
6399 HReg fdst
= newVRegF(env
);
6400 MIPSAMode
*zero_r1
= MIPSAMode_IR(0, StackPointer(mode64
));
6402 sub_from_sp(env
, 16);
6403 /* store as F32, hence truncating */
6404 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fsrc
, zero_r1
));
6405 /* and reload. Good huh?! (sigh) */
6406 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 4, fdst
, zero_r1
));
6411 /* --------- ITE --------- */
6412 if (e
->tag
== Iex_ITE
) {
6413 vassert(typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
);
6414 HReg r0
= iselFltExpr(env
, e
->Iex
.ITE
.iffalse
);
6415 HReg r1
= iselFltExpr(env
, e
->Iex
.ITE
.iftrue
);
6416 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
6417 HReg r_dst
= newVRegF(env
);
6418 #if (__mips_isa_rev >= 6)
6419 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, r_cond
));
6420 addInstr(env
, MIPSInstr_MoveCond(MFpSeld
, r_dst
, r0
, r1
));
6422 addInstr(env
, MIPSInstr_FpUnary((ty
== Ity_F64
) ? Mfp_MOVD
: Mfp_MOVS
,
6424 addInstr(env
, MIPSInstr_MoveCond((ty
== Ity_F64
) ? MFpMoveCond_movnd
:
6426 r_dst
, r1
, r_cond
));
6431 vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e
->tag
);
6433 vpanic("iselFltExpr_wrk(mips)");
6436 static HReg
iselDblExpr(ISelEnv
* env
, IRExpr
* e
)
6438 HReg r
= iselDblExpr_wrk(env
, e
);
6439 vassert(hregClass(r
) == HRcFlt64
);
6440 vassert(hregIsVirtual(r
));
6444 /* DO NOT CALL THIS DIRECTLY */
6445 static HReg
iselDblExpr_wrk(ISelEnv
* env
, IRExpr
* e
)
6447 IRType ty
= typeOfIRExpr(env
->type_env
, e
);
6449 vassert(ty
== Ity_F64
);
6451 if (e
->tag
== Iex_RdTmp
) {
6452 return lookupIRTemp(env
, e
->Iex
.RdTmp
.tmp
);
6455 /* --------- LOAD --------- */
6456 if (e
->tag
== Iex_Load
) {
6457 HReg r_dst
= newVRegD(env
);
6459 vassert(e
->Iex
.Load
.ty
== Ity_F64
);
6460 am_addr
= iselWordExpr_AMode(env
, e
->Iex
.Load
.addr
, ty
);
6461 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, r_dst
, am_addr
));
6465 /* --------- GET --------- */
6466 if (e
->tag
== Iex_Get
) {
6468 HReg r_dst
= newVRegD(env
);
6469 MIPSAMode
*am_addr
= MIPSAMode_IR(e
->Iex
.Get
.offset
,
6470 GuestStatePointer(mode64
));
6471 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */ , 8, r_dst
, am_addr
));
6475 if (e
->tag
== Iex_Unop
) {
6476 MIPSFpOp fpop
= Mfp_INVALID
;
6477 switch (e
->Iex
.Unop
.op
) {
6484 case Iop_F32toF64
: {
6486 HReg src
= iselFltExpr(env
, e
->Iex
.Unop
.arg
);
6487 HReg dst
= newVRegD(env
);
6489 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDS
, dst
, src
));
6492 case Iop_ReinterpI64asF64
: {
6494 HReg dst
= newVRegD(env
);
6496 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Unop
.arg
);
6498 dst
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6501 case Iop_I32StoF64
: {
6503 HReg dst
= newVRegD(env
);
6504 HReg tmp
= newVRegF(env
);
6505 HReg r_src
= iselWordExpr_R(env
, e
->Iex
.Unop
.arg
);
6507 /* Move Word to Floating Point
6509 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, tmp
, r_src
));
6511 /* and do convert */
6512 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDW
, dst
, tmp
));
6520 if (fpop
!= Mfp_INVALID
) {
6521 HReg src
= iselDblExpr(env
, e
->Iex
.Unop
.arg
);
6522 HReg dst
= newVRegD(env
);
6523 addInstr(env
, MIPSInstr_FpUnary(fpop
, dst
, src
));
6528 if (e
->tag
== Iex_Binop
) {
6529 switch (e
->Iex
.Binop
.op
) {
6530 case Iop_RoundF64toInt
: {
6531 HReg src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6532 HReg dst
= newVRegD(env
);
6534 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6535 #if (__mips_isa_rev >= 6)
6536 addInstr(env
, MIPSInstr_FpConvert(Mfp_RINTD
, dst
, src
));
6538 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTLD
, dst
, src
));
6539 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, dst
, dst
));
6542 set_MIPS_rounding_default(env
);
6548 HReg src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6549 HReg dst
= newVRegD(env
);
6550 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6551 addInstr(env
, MIPSInstr_FpUnary(Mfp_SQRTD
, dst
, src
));
6552 set_MIPS_rounding_default(env
);
6556 case Iop_I64StoF64
: {
6557 HReg r_dst
= newVRegD(env
);
6561 tmp
= newVRegD(env
);
6562 fr_src
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6563 /* Move SP down 8 bytes */
6564 sub_from_sp(env
, 8);
6565 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6568 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6570 /* load as Ity_F64 */
6571 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6577 tmp
= newVRegD(env
);
6578 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6579 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6582 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6583 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6584 set_MIPS_rounding_default(env
);
6589 case Iop_I64UtoF64
: {
6591 HReg tmp
= newVRegV(env
);
6592 HReg r_src2h
, r_src2l
;
6594 iselInt64Expr(&r_src2h
, &r_src2l
, env
, e
->Iex
.Binop
.arg2
);
6595 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Binop
.arg1
);
6596 addInstr(env
, MIPSInstr_Msa2R(MSA_FILL
, MSA_W
, r_src2l
, tmp
));
6597 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, tmp
, MSA_DFN_W
| 1));
6598 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2l
, tmp
, MSA_DFN_W
| 2));
6599 addInstr(env
, MIPSInstr_MsaElm(MSA_INSERT
, r_src2h
, tmp
, MSA_DFN_W
| 3));
6600 HReg r_srchh
= newVRegI(env
);
6601 HReg r_srchl
= newVRegI(env
);
6602 addInstr(env
, MIPSInstr_Msa2RF(MSA_FFINT_U
, MSA_F_DW
, tmp
, tmp
));
6603 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srchl
, MSA_DFN_W
| 0));
6604 addInstr(env
, MIPSInstr_MsaElm(MSA_COPY_S
, tmp
, r_srchh
, MSA_DFN_W
| 1));
6605 r_dst
= mk_LoadRR32toFPR(env
, r_srchh
, r_srchl
);
6606 set_MIPS_rounding_default_MSA(env
);
6609 #if (__mips_isa_rev >= 6)
6610 case Iop_MaxNumF64
: {
6611 HReg src1
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
6612 HReg src2
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6613 HReg dst
= newVRegD(env
);
6614 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MAXD
, dst
,
6619 case Iop_MinNumF64
: {
6620 HReg src1
= iselDblExpr(env
, e
->Iex
.Binop
.arg1
);
6621 HReg src2
= iselDblExpr(env
, e
->Iex
.Binop
.arg2
);
6622 HReg dst
= newVRegD(env
);
6623 addInstr(env
, MIPSInstr_FpMinMax(Mfp_MIND
, dst
,
6635 if (e
->tag
== Iex_Triop
) {
6636 switch (e
->Iex
.Triop
.details
->op
) {
6643 HReg argL
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6644 HReg argR
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6645 HReg dst
= newVRegD(env
);
6646 switch (e
->Iex
.Triop
.details
->op
) {
6665 set_MIPS_rounding_mode(env
, e
->Iex
.Triop
.details
->arg1
);
6666 addInstr(env
, MIPSInstr_FpBinary(op
, dst
, argL
, argR
));
6667 set_MIPS_rounding_default(env
);
6671 case Iop_ScaleF64
: {
6672 HReg src1
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg2
);
6673 HReg src2
= iselDblExpr(env
, e
->Iex
.Triop
.details
->arg3
);
6674 HReg v_help
= newVRegV(env
);
6675 HReg dst
= newVRegD(env
);
6677 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Triop
.details
->arg1
);
6678 addInstr(env
, MIPSInstr_Msa2RF(MSA_FTINT_S
, MSA_F_DW
, v_help
, src2
));
6679 addInstr(env
, MIPSInstr_Msa3RF(MSA_FEXP2
, MSA_F_DW
, dst
, src1
, v_help
));
6680 set_MIPS_rounding_default_MSA(env
);
6688 if (e
->tag
== Iex_Qop
) {
6689 switch (e
->Iex
.Qop
.details
->op
) {
6693 switch (e
->Iex
.Qop
.details
->op
) {
6694 #if (__mips_isa_rev >= 6)
6712 HReg dst
= newVRegD(env
);
6713 HReg src1
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg2
);
6714 HReg src2
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg3
);
6715 HReg src3
= iselDblExpr(env
, e
->Iex
.Qop
.details
->arg4
);
6716 #if (__mips_isa_rev >= 6)
6717 set_MIPS_rounding_mode(env
, e
->Iex
.Qop
.details
->arg1
);
6718 addInstr(env
, MIPSInstr_FpTernary(op
, dst
,
6720 set_MIPS_rounding_default(env
);
6723 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, src3
, dst
, 0));
6724 set_MIPS_rounding_mode_MSA(env
, e
->Iex
.Qop
.details
->arg1
);
6725 addInstr(env
, MIPSInstr_Msa3RF(op
, MSA_F_DW
, dst
, src1
, src2
));
6726 set_MIPS_rounding_default_MSA(env
);
6730 case Iop_I64StoF64
: {
6731 HReg r_dst
= newVRegD(env
);
6735 tmp
= newVRegF(env
);
6736 fr_src
= iselWordExpr_R(env
, e
->Iex
.Binop
.arg2
);
6737 /* Move SP down 8 bytes */
6738 sub_from_sp(env
, 8);
6739 am_addr
= MIPSAMode_IR(0, StackPointer(mode64
));
6742 addInstr(env
, MIPSInstr_Store(8, am_addr
, fr_src
, mode64
));
6744 /* load as Ity_F64 */
6745 addInstr(env
, MIPSInstr_FpLdSt(True
/*load */, 8, tmp
, am_addr
));
6751 tmp
= newVRegD(env
);
6752 iselInt64Expr(&Hi
, &Lo
, env
, e
->Iex
.Binop
.arg2
);
6753 tmp
= mk_LoadRR32toFPR(env
, Hi
, Lo
); /* 2*I32 -> F64 */
6756 set_MIPS_rounding_mode(env
, e
->Iex
.Binop
.arg1
);
6757 addInstr(env
, MIPSInstr_FpConvert(Mfp_CVTDL
, r_dst
, tmp
));
6758 set_MIPS_rounding_default(env
);
6768 /* --------- ITE --------- */
6769 if (e
->tag
== Iex_ITE
) {
6771 && typeOfIRExpr(env
->type_env
, e
->Iex
.ITE
.cond
) == Ity_I1
) {
6772 HReg r0
= iselDblExpr(env
, e
->Iex
.ITE
.iffalse
);
6773 HReg r1
= iselDblExpr(env
, e
->Iex
.ITE
.iftrue
);
6774 HReg r_cond
= iselWordExpr_R(env
, e
->Iex
.ITE
.cond
);
6775 HReg r_dst
= newVRegD(env
);
6776 #if (__mips_isa_rev >= 6)
6777 addInstr(env
, MIPSInstr_FpGpMove(MFpGpMove_mtc1
, r_dst
, r_cond
));
6778 addInstr(env
, MIPSInstr_MoveCond(MFpSeld
, r_dst
, r0
, r1
));
6780 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, r_dst
, r0
));
6781 addInstr(env
, MIPSInstr_MoveCond(MFpMoveCond_movnd
, r_dst
, r1
,
6788 vex_printf("iselDblExpr(mips): No such tag(%u)\n", e
->tag
);
6790 vpanic("iselDblExpr_wrk(mips)");
6793 /*---------------------------------------------------------*/
6794 /*--- ISEL: Statements ---*/
6795 /*---------------------------------------------------------*/
6797 static void iselStmt(ISelEnv
* env
, IRStmt
* stmt
)
6799 if (vex_traceflags
& VEX_TRACE_VCODE
) {
6800 vex_printf("\n-- ");
6806 switch (stmt
->tag
) {
6807 /* --------- STORE --------- */
6810 IRType tyd
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.Store
.data
);
6812 if (tyd
== Ity_V128
) {
6814 HReg res
= iselV128Expr(env
, stmt
->Ist
.Store
.data
);
6815 HReg addr
= iselWordExpr_R(env
, stmt
->Ist
.Store
.addr
);
6816 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, 0, addr
, res
, MSA_B
));
6820 /*constructs addressing mode from address provided */
6821 am_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.Store
.addr
, tyd
);
6823 if (tyd
== Ity_I8
|| tyd
== Ity_I16
|| tyd
== Ity_I32
||
6824 (mode64
&& (tyd
== Ity_I64
))) {
6825 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.Store
.data
);
6826 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(tyd
)),
6827 am_addr
, r_src
, mode64
));
6830 if (!mode64
&& (tyd
== Ity_I64
)) {
6832 HReg r_addr
= iselWordExpr_R(env
, stmt
->Ist
.Store
.addr
);
6834 iselInt64Expr(&vHi
, &vLo
, env
, stmt
->Ist
.Store
.data
);
6836 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6837 MIPSAMode_IR(0, r_addr
), vHi
, mode64
));
6838 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6839 MIPSAMode_IR(4, r_addr
), vLo
, mode64
));
6842 if (tyd
== Ity_F32
) {
6843 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Store
.data
);
6844 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fr_src
,
6848 if (tyd
== Ity_F64
&& mode64
) {
6849 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Store
.data
);
6850 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6854 if (!mode64
&& (tyd
== Ity_F64
)) {
6855 HReg fr_src
= iselDblExpr(env
, stmt
->Ist
.Store
.data
);
6856 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6864 /* --------- PUT --------- */
6866 IRType ty
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.Put
.data
);
6868 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
||
6869 (ty
== Ity_I64
&& mode64
)) {
6870 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.Put
.data
);
6871 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6872 GuestStatePointer(mode64
));
6873 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(ty
)),
6874 am_addr
, r_src
, mode64
));
6878 if (ty
== Ity_I64
&& !mode64
) {
6880 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6881 GuestStatePointer(mode64
));
6882 MIPSAMode
*am_addr4
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
+ 4,
6883 GuestStatePointer(mode64
));
6884 iselInt64Expr(&vHi
, &vLo
, env
, stmt
->Ist
.Put
.data
);
6885 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6886 am_addr
, vLo
, mode64
));
6887 addInstr(env
, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32
)),
6888 am_addr4
, vHi
, mode64
));
6893 if (ty
== Ity_F32
) {
6894 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Put
.data
);
6895 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6896 GuestStatePointer(mode64
));
6897 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 4, fr_src
,
6902 if (ty
== Ity_F64
) {
6904 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.Put
.data
);
6905 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6906 GuestStatePointer(mode64
));
6907 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6910 HReg fr_src
= iselDblExpr(env
, stmt
->Ist
.Put
.data
);
6911 MIPSAMode
*am_addr
= MIPSAMode_IR(stmt
->Ist
.Put
.offset
,
6912 GuestStatePointer(mode64
));
6913 addInstr(env
, MIPSInstr_FpLdSt(False
/*store */ , 8, fr_src
,
6918 if (ty
== Ity_V128
) {
6920 HReg v_src
= iselV128Expr(env
, stmt
->Ist
.Put
.data
);
6921 #if defined(_MIPSEB)
6922 HReg r_addr
= newVRegI(env
);
6923 addInstr(env
, MIPSInstr_Alu(mode64
? Malu_DADD
: Malu_ADD
, r_addr
, GuestStatePointer(mode64
),
6924 MIPSRH_Imm(False
, stmt
->Ist
.Put
.offset
)));
6925 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, 0, r_addr
, v_src
, MSA_B
));
6927 vassert(!(stmt
->Ist
.Put
.offset
& 7));
6928 addInstr(env
, MIPSInstr_MsaMi10(MSA_ST
, stmt
->Ist
.Put
.offset
>> 3,
6929 GuestStatePointer(mode64
), v_src
, MSA_D
));
6936 /* --------- TMP --------- */
6938 IRTemp tmp
= stmt
->Ist
.WrTmp
.tmp
;
6939 IRType ty
= typeOfIRTemp(env
->type_env
, tmp
);
6941 if (ty
== Ity_I8
|| ty
== Ity_I16
|| ty
== Ity_I32
|| ty
== Ity_I1
) {
6942 HReg r_dst
= lookupIRTemp(env
, tmp
);
6943 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.WrTmp
.data
);
6944 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
6948 if (ty
== Ity_I64
) {
6950 HReg r_dst
= lookupIRTemp(env
, tmp
);
6951 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.WrTmp
.data
);
6952 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
6955 HReg rHi
, rLo
, dstHi
, dstLo
;
6956 iselInt64Expr(&rHi
, &rLo
, env
, stmt
->Ist
.WrTmp
.data
);
6957 lookupIRTemp64(&dstHi
, &dstLo
, env
, tmp
);
6958 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
6959 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
6964 if (mode64
&& ty
== Ity_I128
) {
6965 HReg rHi
, rLo
, dstHi
, dstLo
;
6966 iselInt128Expr(&rHi
, &rLo
, env
, stmt
->Ist
.WrTmp
.data
);
6967 lookupIRTempPair(&dstHi
, &dstLo
, env
, tmp
);
6968 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
6969 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
6973 if (ty
== Ity_F32
) {
6974 HReg fr_dst
= lookupIRTemp(env
, tmp
);
6975 HReg fr_src
= iselFltExpr(env
, stmt
->Ist
.WrTmp
.data
);
6976 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVS
, fr_dst
, fr_src
));
6980 if (ty
== Ity_F64
) {
6982 HReg src
= iselFltExpr(env
, stmt
->Ist
.WrTmp
.data
);
6983 HReg dst
= lookupIRTemp(env
, tmp
);
6984 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, dst
, src
));
6987 HReg src
= iselDblExpr(env
, stmt
->Ist
.WrTmp
.data
);
6988 HReg dst
= lookupIRTemp(env
, tmp
);
6989 addInstr(env
, MIPSInstr_FpUnary(Mfp_MOVD
, dst
, src
));
6994 if (ty
== Ity_V128
) {
6996 HReg v_dst
= lookupIRTemp(env
, tmp
);
6997 HReg v_src
= iselV128Expr(env
, stmt
->Ist
.WrTmp
.data
);
6998 addInstr(env
, MIPSInstr_MsaElm(MSA_MOVE
, v_src
, v_dst
, 0));
7004 /* --------- Call to DIRTY helper --------- */
7006 IRDirty
*d
= stmt
->Ist
.Dirty
.details
;
7008 /* Figure out the return type, if any. */
7009 IRType retty
= Ity_INVALID
;
7010 if (d
->tmp
!= IRTemp_INVALID
)
7011 retty
= typeOfIRTemp(env
->type_env
, d
->tmp
);
7013 /* Throw out any return types we don't know about. */
7014 Bool retty_ok
= False
;
7016 case Ity_INVALID
: /* Function doesn't return anything. */
7018 case Ity_I64
: case Ity_I32
: case Ity_I16
: case Ity_I8
:
7019 retty_ok
= True
; break;
7025 break; /* will go to stmt_fail: */
7027 /* Marshal args, do the call, clear stack, set the return value
7028 to 0x555..555 if this is a conditional call that returns a
7029 value and the call is skipped. */
7031 RetLoc rloc
= mk_RetLoc_INVALID();
7032 doHelperCall( &addToSp
, &rloc
, env
, d
->guard
, d
->cee
, retty
, d
->args
);
7033 vassert(is_sane_RetLoc(rloc
));
7035 /* Now figure out what to do with the returned value, if any. */
7038 /* No return value. Nothing to do. */
7039 vassert(d
->tmp
== IRTemp_INVALID
);
7040 vassert(rloc
.pri
== RLPri_None
);
7041 vassert(addToSp
== 0);
7044 case Ity_I32
: case Ity_I16
: case Ity_I8
: {
7045 /* The returned value is in $v0. Park it in the register
7046 associated with tmp. */
7047 HReg r_dst
= lookupIRTemp(env
, d
->tmp
);
7048 addInstr(env
, MIPSInstr_Shft(Mshft_SLL
, True
, r_dst
,
7049 hregMIPS_GPR2(mode64
),
7050 MIPSRH_Imm(False
, 0)));
7051 vassert(rloc
.pri
== RLPri_Int
);
7052 vassert(addToSp
== 0);
7057 /* The returned value is in $v0. Park it in the register
7058 associated with tmp. */
7059 HReg r_dst
= lookupIRTemp(env
, d
->tmp
);
7060 addInstr(env
, mk_iMOVds_RR(r_dst
, hregMIPS_GPR2(mode64
)));
7061 vassert(rloc
.pri
== RLPri_Int
);
7062 vassert(addToSp
== 0);
7065 HReg rHi
= newVRegI(env
);
7066 HReg rLo
= newVRegI(env
);
7068 addInstr(env
, mk_iMOVds_RR(rLo
, hregMIPS_GPR2(mode64
)));
7069 addInstr(env
, mk_iMOVds_RR(rHi
, hregMIPS_GPR3(mode64
)));
7070 lookupIRTemp64(&dstHi
, &dstLo
, env
, d
->tmp
);
7071 addInstr(env
, mk_iMOVds_RR(dstHi
, rHi
));
7072 addInstr(env
, mk_iMOVds_RR(dstLo
, rLo
));
7078 vassert(rloc
.pri
== RLPri_V128SpRel
);
7079 vassert((rloc
.spOff
< 512) && (rloc
.spOff
> -512));
7080 vassert(addToSp
>= 16);
7081 HReg dst
= lookupIRTemp(env
, d
->tmp
);
7082 addInstr(env
, MIPSInstr_MsaMi10(MSA_LD
, rloc
.spOff
, StackPointer(mode64
), dst
, MSA_B
));
7083 add_to_sp(env
, addToSp
);
7093 /* --------- Load Linked or Store Conditional --------- */
7095 /* Temporary solution; this need to be rewritten again for MIPS.
7096 On MIPS you can not read from address that is locked with LL
7097 before SC. If you read from address that is locked than SC will
7099 IRTemp res
= stmt
->Ist
.LLSC
.result
;
7100 IRType tyRes
= typeOfIRTemp(env
->type_env
, res
);
7101 IRType tyAddr
= typeOfIRExpr(env
->type_env
, stmt
->Ist
.LLSC
.addr
);
7103 if (!mode64
&& (tyAddr
!= Ity_I32
))
7106 if (stmt
->Ist
.LLSC
.storedata
== NULL
) {
7109 /* constructs addressing mode from address provided */
7110 r_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.LLSC
.addr
, tyAddr
);
7112 HReg r_dst
= lookupIRTemp(env
, res
);
7113 if (tyRes
== Ity_I32
) {
7114 addInstr(env
, MIPSInstr_LoadL(4, r_dst
, r_addr
, mode64
));
7116 } else if (tyRes
== Ity_I64
&& mode64
) {
7117 addInstr(env
, MIPSInstr_LoadL(8, r_dst
, r_addr
, mode64
));
7123 r_addr
= iselWordExpr_AMode(env
, stmt
->Ist
.LLSC
.addr
, tyAddr
);
7124 HReg r_src
= iselWordExpr_R(env
, stmt
->Ist
.LLSC
.storedata
);
7125 HReg r_dst
= lookupIRTemp(env
, res
);
7126 IRType tyData
= typeOfIRExpr(env
->type_env
,
7127 stmt
->Ist
.LLSC
.storedata
);
7129 if (tyData
== Ity_I32
) {
7130 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
7131 addInstr(env
, MIPSInstr_StoreC(4, r_addr
, r_dst
, mode64
));
7133 } else if (tyData
== Ity_I64
&& mode64
) {
7134 addInstr(env
, mk_iMOVds_RR(r_dst
, r_src
));
7135 addInstr(env
, MIPSInstr_StoreC(8, r_addr
, r_dst
, mode64
));
7143 if (stmt
->Ist
.CAS
.details
->oldHi
== IRTemp_INVALID
) {
7144 IRCAS
*cas
= stmt
->Ist
.CAS
.details
;
7145 HReg old
= lookupIRTemp(env
, cas
->oldLo
);
7146 HReg addr
= iselWordExpr_R(env
, cas
->addr
);
7147 HReg expd
= iselWordExpr_R(env
, cas
->expdLo
);
7148 HReg data
= iselWordExpr_R(env
, cas
->dataLo
);
7149 if (typeOfIRTemp(env
->type_env
, cas
->oldLo
) == Ity_I64
) {
7150 addInstr(env
, MIPSInstr_Cas(8, old
, addr
, expd
, data
, mode64
));
7151 } else if (typeOfIRTemp(env
->type_env
, cas
->oldLo
) == Ity_I32
) {
7152 addInstr(env
, MIPSInstr_Cas(4, old
, addr
, expd
, data
, mode64
));
7157 /* --------- INSTR MARK --------- */
7158 /* Doesn't generate any executable code ... */
7162 /* --------- ABI HINT --------- */
7163 /* These have no meaning (denotation in the IR) and so we ignore
7164 them ... if any actually made it this far. */
7168 /* --------- NO-OP --------- */
7169 /* Fairly self-explanatory, wouldn't you say? */
7173 /* --------- EXIT --------- */
7175 IRConst
* dst
= stmt
->Ist
.Exit
.dst
;
7176 if (!mode64
&& dst
->tag
!= Ico_U32
)
7177 vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
7178 if (mode64
&& dst
->tag
!= Ico_U64
)
7179 vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
7181 MIPSCondCode cc
= iselCondCode(env
, stmt
->Ist
.Exit
.guard
);
7182 MIPSAMode
* amPC
= MIPSAMode_IR(stmt
->Ist
.Exit
.offsIP
,
7183 GuestStatePointer(mode64
));
7185 /* Case: boring transfer to known address */
7186 if (stmt
->Ist
.Exit
.jk
== Ijk_Boring
7187 || stmt
->Ist
.Exit
.jk
== Ijk_Call
7188 /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
7189 if (env
->chainingAllowed
) {
7190 /* .. almost always true .. */
7191 /* Skip the event check at the dst if this is a forwards
7195 ? (((Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U64
) > (Addr64
)env
->max_ga
)
7196 : (((Addr32
)stmt
->Ist
.Exit
.dst
->Ico
.U32
) > (Addr32
)env
->max_ga
);
7197 if (0) vex_printf("%s", toFastEP
? "Y" : ",");
7198 addInstr(env
, MIPSInstr_XDirect(
7199 mode64
? (Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U64
7200 : (Addr64
)stmt
->Ist
.Exit
.dst
->Ico
.U32
,
7201 amPC
, cc
, toFastEP
));
7203 /* .. very occasionally .. */
7204 /* We can't use chaining, so ask for an assisted transfer,
7205 as that's the only alternative that is allowable. */
7206 HReg r
= iselWordExpr_R(env
, IRExpr_Const(stmt
->Ist
.Exit
.dst
));
7207 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, cc
, Ijk_Boring
));
7212 /* Case: assisted transfer to arbitrary address */
7213 switch (stmt
->Ist
.Exit
.jk
) {
7214 /* Keep this list in sync with that in iselNext below */
7223 case Ijk_SigFPE_IntDiv
:
7224 case Ijk_SigFPE_IntOvf
:
7225 case Ijk_Sys_syscall
:
7226 case Ijk_InvalICache
:
7228 HReg r
= iselWordExpr_R(env
, IRExpr_Const(stmt
->Ist
.Exit
.dst
));
7229 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, cc
,
7230 stmt
->Ist
.Exit
.jk
));
7237 /* Do we ever expect to see any other kind? */
7246 vex_printf("stmt_fail tag: 0x%x\n", stmt
->tag
);
7248 vpanic("iselStmt:\n");
7251 /*---------------------------------------------------------*/
7252 /*--- ISEL: Basic block terminators (Nexts) ---*/
7253 /*---------------------------------------------------------*/
7255 static void iselNext ( ISelEnv
* env
,
7256 IRExpr
* next
, IRJumpKind jk
, Int offsIP
)
7258 if (vex_traceflags
& VEX_TRACE_VCODE
) {
7259 vex_printf( "\n-- PUT(%d) = ", offsIP
);
7261 vex_printf( "; exit-");
7266 /* Case: boring transfer to known address */
7267 if (next
->tag
== Iex_Const
) {
7268 IRConst
* cdst
= next
->Iex
.Const
.con
;
7269 vassert(cdst
->tag
== (env
->mode64
? Ico_U64
:Ico_U32
));
7270 if (jk
== Ijk_Boring
|| jk
== Ijk_Call
) {
7271 /* Boring transfer to known address */
7272 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
, GuestStatePointer(env
->mode64
));
7273 if (env
->chainingAllowed
) {
7274 /* .. almost always true .. */
7275 /* Skip the event check at the dst if this is a forwards
7279 ? (((Addr64
)cdst
->Ico
.U64
) > (Addr64
)env
->max_ga
)
7280 : (((Addr32
)cdst
->Ico
.U32
) > (Addr32
)env
->max_ga
);
7281 if (0) vex_printf("%s", toFastEP
? "X" : ".");
7282 addInstr(env
, MIPSInstr_XDirect(
7283 env
->mode64
? (Addr64
)cdst
->Ico
.U64
7284 : (Addr64
)cdst
->Ico
.U32
,
7285 amPC
, MIPScc_AL
, toFastEP
));
7287 /* .. very occasionally .. */
7288 /* We can't use chaining, so ask for an assisted transfer,
7289 as that's the only alternative that is allowable. */
7290 HReg r
= iselWordExpr_R(env
, next
);
7291 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
,
7298 /* Case: call/return (==boring) transfer to any address */
7300 case Ijk_Boring
: case Ijk_Ret
: case Ijk_Call
: {
7301 HReg r
= iselWordExpr_R(env
, next
);
7302 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
,
7303 GuestStatePointer(env
->mode64
));
7304 if (env
->chainingAllowed
) {
7305 addInstr(env
, MIPSInstr_XIndir(r
, amPC
, MIPScc_AL
));
7307 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
,
7316 /* Case: assisted transfer to arbitrary address */
7318 /* Keep this list in sync with that for Ist_Exit above */
7327 case Ijk_SigFPE_IntDiv
:
7328 case Ijk_SigFPE_IntOvf
:
7329 case Ijk_Sys_syscall
:
7330 case Ijk_InvalICache
: {
7331 HReg r
= iselWordExpr_R(env
, next
);
7332 MIPSAMode
* amPC
= MIPSAMode_IR(offsIP
, GuestStatePointer(env
->mode64
));
7333 addInstr(env
, MIPSInstr_XAssisted(r
, amPC
, MIPScc_AL
, jk
));
7340 vex_printf("\n-- PUT(%d) = ", offsIP
);
7342 vex_printf("; exit-");
7345 vassert(0); /* are we expecting any other kind? */
7348 /*---------------------------------------------------------*/
7349 /*--- Insn selector top-level ---*/
7350 /*---------------------------------------------------------*/
7352 /* Translate an entire BB to mips code. */
7353 HInstrArray
*iselSB_MIPS ( const IRSB
* bb
,
7355 const VexArchInfo
* archinfo_host
,
7356 const VexAbiInfo
* vbi
,
7357 Int offs_Host_EvC_Counter
,
7358 Int offs_Host_EvC_FailAddr
,
7359 Bool chainingAllowed
,
7366 MIPSAMode
*amCounter
, *amFailAddr
;
7368 hwcaps_host
= archinfo_host
->hwcaps
;
7371 vassert(arch_host
== VexArchMIPS32
|| arch_host
== VexArchMIPS64
);
7372 vassert(VEX_PRID_COMP_MIPS
== VEX_MIPS_COMP_ID(hwcaps_host
)
7373 || VEX_PRID_COMP_CAVIUM
== VEX_MIPS_COMP_ID(hwcaps_host
)
7374 || VEX_PRID_COMP_BROADCOM
== VEX_MIPS_COMP_ID(hwcaps_host
)
7375 || VEX_PRID_COMP_NETLOGIC
== VEX_MIPS_COMP_ID(hwcaps_host
)
7376 || VEX_PRID_COMP_INGENIC_E1
== VEX_MIPS_COMP_ID(hwcaps_host
)
7377 || VEX_PRID_COMP_LEGACY
== VEX_MIPS_COMP_ID(hwcaps_host
));
7379 /* Check that the host's endianness is as expected. */
7380 vassert(archinfo_host
->endness
== VexEndnessLE
7381 || archinfo_host
->endness
== VexEndnessBE
);
7383 mode64
= arch_host
!= VexArchMIPS32
;
7384 fp_mode64
= VEX_MIPS_HOST_FP_MODE(hwcaps_host
);
7385 has_msa
= VEX_MIPS_PROC_MSA(archinfo_host
->hwcaps
);
7387 /* Make up an initial environment to use. */
7388 env
= LibVEX_Alloc_inline(sizeof(ISelEnv
));
7390 env
->mode64
= mode64
;
7391 env
->fp_mode64
= fp_mode64
;
7393 /* Set up output code array. */
7394 env
->code
= newHInstrArray();
7396 /* Copy BB's type env. */
7397 env
->type_env
= bb
->tyenv
;
7399 /* Make up an IRTemp -> virtual HReg mapping. This doesn't
7400 change as we go along. */
7401 env
->n_vregmap
= bb
->tyenv
->types_used
;
7402 env
->vregmap
= LibVEX_Alloc_inline(env
->n_vregmap
* sizeof(HReg
));
7403 env
->vregmapHI
= LibVEX_Alloc_inline(env
->n_vregmap
* sizeof(HReg
));
7405 /* and finally ... */
7406 env
->hwcaps
= hwcaps_host
;
7407 env
->chainingAllowed
= chainingAllowed
;
7408 env
->hwcaps
= hwcaps_host
;
7409 env
->max_ga
= max_ga
;
7411 /* For each IR temporary, allocate a suitably-kinded virtual
7414 for (i
= 0; i
< env
->n_vregmap
; i
++) {
7415 hregHI
= hreg
= INVALID_HREG
;
7416 switch (bb
->tyenv
->types
[i
]) {
7422 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7425 hreg
= mkHReg(True
, HRcInt32
, 0, j
++);
7430 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7433 hreg
= mkHReg(True
, HRcInt32
, 0, j
++);
7434 hregHI
= mkHReg(True
, HRcInt32
, 0, j
++);
7439 hreg
= mkHReg(True
, HRcInt64
, 0, j
++);
7440 hregHI
= mkHReg(True
, HRcInt64
, 0, j
++);
7444 hreg
= mkHReg(True
, HRcFlt64
, 0, j
++);
7447 hreg
= mkHReg(True
, HRcFlt32
, 0, j
++);
7451 hreg
= mkHReg(True
, HRcFlt64
, 0, j
++);
7454 hreg
= mkHReg(True
, HRcVec128
, 0, j
++);
7457 ppIRType(bb
->tyenv
->types
[i
]);
7458 vpanic("iselBB(mips): IRTemp type");
7461 env
->vregmap
[i
] = hreg
;
7462 env
->vregmapHI
[i
] = hregHI
;
7466 /* The very first instruction must be an event check. */
7467 amCounter
= MIPSAMode_IR(offs_Host_EvC_Counter
, GuestStatePointer(mode64
));
7468 amFailAddr
= MIPSAMode_IR(offs_Host_EvC_FailAddr
, GuestStatePointer(mode64
));
7469 addInstr(env
, MIPSInstr_EvCheck(amCounter
, amFailAddr
));
7471 /* Possibly a block counter increment (for profiling). At this
7472 point we don't know the address of the counter, so just pretend
7473 it is zero. It will have to be patched later, but before this
7474 translation is used, by a call to LibVEX_patchProfCtr. */
7476 addInstr(env
, MIPSInstr_ProfInc());
7479 /* Ok, finally we can iterate over the statements. */
7480 for (i
= 0; i
< bb
->stmts_used
; i
++)
7481 iselStmt(env
, bb
->stmts
[i
]);
7483 iselNext(env
, bb
->next
, bb
->jumpkind
, bb
->offsIP
);
7485 /* record the number of vregs we used. */
7486 env
->code
->n_vregs
= env
->vreg_ctr
;
7491 /*---------------------------------------------------------------*/
7492 /*--- end host_mips_isel.c ---*/
7493 /*---------------------------------------------------------------*/